home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DTP / DTP_TEX / 3238.ZIP / DVIEPS2.ZIP / DVIFONTS.C < prev    next >
C/C++ Source or Header  |  1988-11-01  |  85KB  |  2,398 lines

  1. /*=======================================================================
  2. *    Program : dvifonts.c
  3. *    Purpose : font related code for eps device driver
  4. *       Date : Oct 1988
  5. *========================================================================
  6. *   Compiler : Microsoft V5.1 C Compiler
  7. *     Linker : Microsoft V3.61 Linker
  8. * Enviroment : MS-DOS 3.21
  9. *========================================================================
  10. * Edit History
  11. *
  12. *   /  /   -gbm- 
  13. *
  14. *======================================================================*/
  15.  
  16. #include "dvidefs.h"
  17. #include "dvivars.h"
  18.  
  19. extern double mag_table[99];
  20.  
  21. /***********************************************************************
  22. Compute the actual size factor given the integer approximation unmodsize
  23. = (magnification  factor)*1000.   Values  not found  in  the  table  are
  24. rounded to the nearest table  entry; this ensures that rounding  errors,
  25. or  user  magnification  parameter  input  errors  result  in  something
  26. reasonable.  mag_table[] has a  wider range of magnifications  available
  27. than most sites will have, and can be used to find a nearest match  font
  28. when one is missing.
  29. ***********************************************************************/
  30.  
  31. double actfact(register unsigned long int unmodsize)
  32.  
  33.    {
  34.    register int k;
  35.    register unsigned long int tab_entry;
  36.  
  37.    for (k = 1; k < MAGTABSIZE; ++k)
  38.       {
  39.       tab_entry = MAGSIZE(mag_table[k]);    /* round entry */
  40.       if (unmodsize < tab_entry) /* choose nearer of k-1,k entries */
  41.          {
  42.          if (unmodsize < MAGSIZE((mag_table[k-1] + mag_table[k])/2.0))
  43.             k--;            /* choose smaller one */
  44.          break;
  45.          }
  46.       else if (unmodsize == tab_entry)
  47.          break;
  48.       }
  49.    mag_index = ((k < MAGTABSIZE) ? k : (MAGTABSIZE-1));/* set global index */
  50.    return((double)mag_table[mag_index]);
  51.    }
  52.  
  53.  
  54. int chargf(c, outfcn)    /* return 0 on success, and EOF on failure */
  55. unsigned char c;            /* current character value */
  56. void (*outfcn)();    /* (possibly NULL) function to output current row */
  57.    {
  58.    unsigned int d;            /* step in m index */
  59.    int do_output;        /* FALSE if outfcn is NULL */
  60.    register unsigned int k;    /* loop step */
  61.    register int m,n;        /* column,row indices in image[n][m] */
  62.    long p;            /* pointer into font file */
  63.    unsigned char paint_switch;        /* alternates between BLACK and WHITE */
  64.    struct char_entry *tcharptr;/* temporary char_entry pointer */
  65.    register unsigned char the_byte;    /* current command byte */
  66.    unsigned long int the_word;        /* temporary result holder */
  67.  
  68.    /* NB: We only test for equality with BLACK.   WHITE is any non-zero
  69. bit pattern, so we cannot test for equality with it */
  70. #define BLACK ((unsigned char)0)
  71. #define WHITE ((unsigned char)(!BLACK))
  72.  
  73.    /*******************************************************************
  74.     This function is called to process a single character description in
  75.     the GF font file,  and to set the  character metrics hp, wp,  xoffp,
  76.     and yoffp for it.  The character  description may start either at  a
  77.     special (XXX) command, or at a beginning-of-character (BOC or  BOC1)
  78.     command.   It  processes  the  character  description  up  to,   and
  79.     including, the end-of-character (EOC) command which terminates it.
  80.  
  81.     The GF  raster description  is encoded  in a  complex form,  but  is
  82.     guaranteed to step across raster rows  from left to right, and  down
  83.     from the  top  row  to  bottom  row,  such  that  in  references  to
  84.     image[n][m], m never decreases in a row, and n never increases in  a
  85.     character.  This means that we  only require enough memory space  to
  86.     hold one row, provided that outfcn(c,yoff) is called each time a row
  87.     is     completed.    This   is   an    important   economization    for
  88.     high-resolution output  devices --  e.g. a  10pt character  at  2400
  89.     dots/inch would require about  8Kb for the  entire image, but  fewer
  90.     than 25 bytes for a  single row.  A 72pt  character (such as in  the
  91.     aminch font) would need  about 430Kb for the  image, but only  about
  92.     200 bytes for a row.
  93.  
  94.     Access to bit m in the current row is controlled through the  macros
  95.     SETBIT(m) and  TESTBIT(m) so  we  need not  be concerned  about  the
  96.     details of bit masking.  Too bad C does not have a bit data type!
  97.  
  98.     The row image is recorded in such a way that bits min_m .. max_m are
  99.     mapped onto  bits  0  ..  (max_m -  min_m)  in  img_row[],  so  that
  100.     outfcn(c,yoff) should be relieved of any shifting operations.
  101.  
  102.     outfcn(c,yoff) is NEVER called if either of hp or wp is <= 0, or if
  103.     if it is NULL.
  104.     *******************************************************************/
  105.  
  106.    if ((c < FIRSTPXLCHAR) || (LASTPXLCHAR < c))
  107.       {
  108.       (void)warning(
  109.       "chargf():  Character value out of range for GF font file");
  110.       return(EOF);
  111.       }
  112.    tcharptr = &(fontptr->ch[c]);
  113.  
  114.    p = (long)tcharptr->fontrp;        /* font file raster pointer */
  115.    if (p < 0L)
  116.       {
  117.       (void)warning(
  118.       "chargf():  Requested character not found in GF font file");
  119.       return(EOF);
  120.       }
  121.    if (fseek(fontfp,p,0))
  122.       {
  123.       (void)warning(
  124.       "chargf():  fseek() failure for GF font file character raster");
  125.       return(EOF);
  126.       }
  127.  
  128.    do_output = (int)(outfcn != (void(*)())NULL);
  129.  
  130.    (void)skgfspec();            /* skip any GF special commands */
  131.  
  132.    the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
  133.    if ((the_byte != GFBOC) && (the_byte != GFBOC1))
  134.       {
  135.       (void)warning(
  136.       "chargf():  GF font file not positioned at BOC or BOC1 command");
  137.       return(EOF);
  138.       }
  139.  
  140.    for (;;)    /* loop with exit at EOC, or at BOC or BOC1 if no rasters */
  141.       {
  142.       switch (the_byte)
  143.          {
  144.       case GFPAINT0:
  145.          paint_switch = (unsigned char)(!paint_switch);
  146.          break;
  147.  
  148.       case GFPAINT1:
  149.          d = (unsigned int)nosignex(fontfp,(unsigned char)1);
  150.          if (do_output && (paint_switch == BLACK))
  151.             {
  152.             for (k = 0; k < d; (++m, ++k))
  153.                SETBIT(m);
  154.             }
  155.          else
  156.             m += (int)d;
  157.          paint_switch = (unsigned char)(!paint_switch);
  158.          break;
  159.  
  160.       case GFPAINT2:
  161.          d = (unsigned int)nosignex(fontfp,(unsigned char)2);
  162.          if (do_output && (paint_switch == BLACK))
  163.             {
  164.             for (k = 0; k < d; (++m, ++k))
  165.                SETBIT(m);
  166.             }
  167.          else
  168.             m += (int)d;
  169.          paint_switch = (unsigned char)(!paint_switch);
  170.          break;
  171.  
  172.       case GFPAINT3:            /* METAFONT never needs this */
  173.          d = (unsigned int)nosignex(fontfp,(unsigned char)3);    /* NOTE: truncation */
  174.          if (do_output && (paint_switch == BLACK))
  175.             {
  176.             for (k = 0; k < d; (++m, ++k))
  177.                SETBIT(m);
  178.             }
  179.          else
  180.             m += (int)d;
  181.          paint_switch = (unsigned char)(!paint_switch);
  182.          break;
  183.  
  184.       case GFBOC:    /* beginning-of-character -- long form */
  185.          the_word = (unsigned long int)nosignex(fontfp,(unsigned char)4);
  186.          p = (long)signex(fontfp,(unsigned char)4);
  187.          if ((unsigned long int)c != the_word)
  188.             {
  189.             if (p < 0L)
  190.                {
  191.                (void)warning(
  192.                "chargf():    Requested character not found in back chain in GF font file");
  193.                return(EOF);
  194.                }
  195.             else
  196.                (void)fseek(fontfp,p,0);    /* must follow back chain */
  197.             break;
  198.             }
  199.          else
  200.             {
  201.             min_m = (int)signex(fontfp,(unsigned char)4);
  202.             max_m = (int)signex(fontfp,(unsigned char)4);
  203.             min_n = (int)signex(fontfp,(unsigned char)4);
  204.             max_n = (int)signex(fontfp,(unsigned char)4);
  205.             }
  206.          if ((min_m < MIN_M) || (MAX_M < max_m) ||
  207.             (min_n < MIN_N) || (MAX_N < max_n))
  208.             {
  209.             (void)warning(
  210.             "chargf():  GF font file character box too large for me");
  211.             return(EOF);
  212.             }
  213.          m = min_m;
  214.          n = max_n;
  215.          paint_switch = WHITE;
  216.          img_words = (unsigned int)((max_m - min_m + 1 + 31) >> 5);
  217.          if (do_output)
  218.             (void)clrrow();
  219.          tcharptr->hp = (int)(max_n - min_n + 1);
  220.          tcharptr->wp = (int)(max_m - min_m + 1);
  221.          tcharptr->xoffp = -(int)(min_m);
  222.          tcharptr->yoffp = (int)(max_n);
  223.          if (!VISIBLE(tcharptr))
  224.             return(0); /* empty character raster -- nothing to output */
  225.          break;
  226.  
  227.       case GFBOC1:        /* beginning-of-character -- short form */
  228.          if (c != (unsigned char)nosignex(fontfp,(unsigned char)1))
  229.             {
  230.             (void)warning(
  231.             "chargf():    Requested character not found in GF font file");
  232.             return(EOF);
  233.             }
  234.          else
  235.             {
  236.             min_m = (int)nosignex(fontfp,(unsigned char)1);
  237.             max_m = (int)nosignex(fontfp,(unsigned char)1);
  238.             min_m = max_m - min_m;
  239.             min_n = (int)nosignex(fontfp,(unsigned char)1);
  240.             max_n = (int)nosignex(fontfp,(unsigned char)1);
  241.             min_n = max_n - min_n;
  242.             }
  243.          if ((min_m < MIN_M) || (MAX_M < max_m) ||
  244.             (min_n < MIN_N) || (MAX_N < max_n))
  245.             {
  246.             (void)warning(
  247.             "chargf():  GF font file character box too large for me");
  248.             return(EOF);
  249.             }
  250.          m = min_m;
  251.          n = max_n;
  252.          paint_switch = WHITE;
  253.          img_words = (unsigned int)((max_m - min_m + 1 + 31) >> 5);
  254.          if (do_output)
  255.             (void)clrrow();
  256.          tcharptr->hp = (int)(max_n - min_n + 1);
  257.          tcharptr->wp = (int)(max_m - min_m + 1);
  258.          tcharptr->xoffp = -(int)(min_m);
  259.          tcharptr->yoffp = (int)(max_n);
  260.          if (!VISIBLE(tcharptr))
  261.             return(0);/* empty character raster -- nothing to output */
  262.          break;
  263.  
  264.       case GFEOC:            /* end-of-character */
  265.          if (do_output)
  266.             {
  267.             (void)(*outfcn)(c,max_n-n);    /* output current row */
  268.             (void)clrrow();        /* clear next one */
  269.             --n;            /* advance to next row below */
  270.             for ( ; n >= min_n ; --n)    /* output any remaining rows */
  271.                (void)(*outfcn)(c,max_n-n);
  272.             }
  273.          return(0);            /* exit outer loop */
  274.  
  275.       case GFSKIP0:
  276.          if (do_output)
  277.             {
  278.             (void)(*outfcn)(c,max_n-n);    /* output current row */
  279.             (void)clrrow();        /* clear next one */
  280.             }
  281.          --n;            /* advance to next row below */
  282.          m = min_m;
  283.          paint_switch = WHITE;
  284.          break;
  285.  
  286.       case GFSKIP1:
  287.          if (do_output)
  288.             {
  289.             (void)(*outfcn)(c,max_n-n);    /* output current row */
  290.             (void)clrrow();        /* clear next one */
  291.             }
  292.          --n;            /* advance to next row below */
  293.          d = (unsigned int)nosignex(fontfp,(unsigned char)1);
  294.          if (do_output)
  295.             {
  296.             for (k = 0; k < d; (--n,++k))    /* output d white rows */
  297.                (void)(*outfcn)(c,max_n-n);
  298.             }
  299.          else
  300.             n -= (int)d;
  301.          m = min_m;
  302.          paint_switch = WHITE;
  303.          break;
  304.  
  305.       case GFSKIP2:
  306.          if (do_output)
  307.             {
  308.             (void)(*outfcn)(c,max_n-n);    /* output current row */
  309.             (void)clrrow();        /* clear next one */
  310.             }
  311.          --n;            /* advance to next row below */
  312.          d = (unsigned int)nosignex(fontfp,(unsigned char)2);
  313.          if (do_output)
  314.             {
  315.             for (k = 0; k < d; (--n,++k))    /* output d white rows */
  316.                (void)(*outfcn)(c,max_n-n);
  317.             }
  318.          else
  319.             n -= (int)d;
  320.          m = min_m;
  321.          paint_switch = WHITE;
  322.          break;
  323.  
  324.       case GFSKIP3:            /* METAFONT never needs this */
  325.          if (do_output)
  326.             {
  327.             (void)(*outfcn)(c,max_n-n);    /* output current row */
  328.             (void)clrrow();        /* clear next one */
  329.             }
  330.          --n;            /* advance to next row below */
  331.          d = (unsigned int)nosignex(fontfp,(unsigned char)3);    /* NOTE truncation */
  332.          if (do_output)
  333.             {
  334.             for (k = 0; k < d; (++k, --n))    /* output d white rows */
  335.                (void)(*outfcn)(c,max_n-n);
  336.             }
  337.          else
  338.             n -= (int)d;
  339.          m = min_m;
  340.          paint_switch = WHITE;
  341.          break;
  342.  
  343.       case GFXXX1:
  344.       case GFXXX2:
  345.       case GFXXX3:
  346.       case GFXXX4:
  347.       case GFYYY:
  348.       case GFNOOP:
  349.          (void)ungetc((char)the_byte,fontfp);
  350.          (void)skgfspec();
  351.          break;
  352.  
  353.       default:
  354.          if (((unsigned char)GFPAINT0 < the_byte) && (the_byte < GFPAINT1))
  355.             {
  356.             d = (unsigned int)(the_byte - GFPAINT0);
  357.             if (do_output && (paint_switch == BLACK))
  358.                {
  359.                for (k = 0; k < d; (++m, ++k))
  360.                   SETBIT(m);
  361.                }
  362.             else
  363.                m += (int)d;
  364.             paint_switch = (unsigned char)(!paint_switch);
  365.             }
  366.          else if (((unsigned char)GFNROW0 <= the_byte) && (the_byte <= GFNROWMAX))
  367.             {
  368.             if (do_output)
  369.                {
  370.                (void)(*outfcn)(c,max_n-n);    /* output current row */
  371.                (void)clrrow();    /* clear next one */
  372.                }
  373.             n--;            /* advance to next row below */
  374.             paint_switch = BLACK;
  375.             m = min_m + (unsigned int)(the_byte - GFNROW0);
  376.             }
  377.          else
  378.             {
  379.             (void)sprintf(message,
  380.             "chargf():  Unexpected byte %d (0x%02x) in GF font file \
  381. at position %ld",
  382.             the_byte,the_byte,(long)ftell(fontfp));
  383.             (void)warning(message);
  384.             return(EOF);
  385.             }
  386.          break;
  387.          }                /* end switch */
  388.       the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
  389.       }                    /* end for() */
  390.    }
  391.  
  392. /* This file departs from all others in the DVIxxx family in that it
  393. declares some private functions and globals which are required nowhere
  394. else.  Only charpk() is called from outside. */
  395.  
  396.    unsigned char get_bit();            /* return next bit from file */
  397. unsigned char get_nybble();        /* return next 4-bit nybble from file */
  398. unsigned int pk_packed_num();    /* get packed number from file */
  399.  
  400. unsigned char bit_weight;        /* weight of current bit in next_byte */
  401. unsigned char dyn_f;            /* dynamic packing flag */
  402. unsigned int repeat_count;        /* how many times to repeat next row */
  403. unsigned char next_byte;            /* current input byte */
  404. unsigned char word_weight;        /* weight of current bit in *pword */
  405.  
  406. /**********************************************************************/
  407.  
  408. int charpk(c,outfcn)    /* return 0 on success, and EOF on failure */
  409. unsigned char c;            /* current character value */
  410. void (*outfcn)();    /* (possibly NULL) function to output current row */
  411.    {
  412.    int count;        /* how many bits of current color left */
  413.    unsigned int c_width;        /* character width in dots */
  414.    unsigned int c_height;        /* character height in dots */
  415.    int do_output;        /* FALSE if outfcn is NULL */
  416.    register unsigned char flag_byte;    /* current file flag byte */
  417.    unsigned int h_bit;        /* horizontal position in row */
  418.    register unsigned int i;    /* loop index */
  419.    register unsigned int k;    /* loop index */
  420.    long offset;        /* offset into font file */
  421.    long p;            /* pointer into font file */
  422.    unsigned long int packet_length;    /* packet length */
  423.    unsigned long int* pword;        /* pointer into img_row[] */
  424.    int rows_left;        /* how many rows left */
  425.    struct char_entry *tcharptr;/* temporary char_entry pointer */
  426.    unsigned char turn_on;        /* initial black/white flag */
  427.  
  428.    /*******************************************************************
  429.     This function is called to process a single character description in
  430.     the  PK  font  file.   The     character  packet  is  pointed  to   by
  431.     fontptr->ch[c].fontrp, and was set by readpk(), which moved past any
  432.     special commands that precede the packet.
  433.  
  434.     The PK  raster description  is encoded  in a  complex form,  but  is
  435.     guaranteed to step across raster rows  from left to right, and  down
  436.     from the  top  row  to  bottom  row,  such  that  in  references  to
  437.     image[n][m], m never decreases in a row, and n never increases in  a
  438.     character.  This means that we  only require enough memory space  to
  439.     hold one row, provided that outfcn(c,yoff) is called each time a row
  440.     is     completed.    This   is   an    important   economization    for
  441.     high-resolution output  devices --  e.g. a  10pt character  at  2400
  442.     dots/inch would require about  8Kb for the  entire image, but  fewer
  443.     than 25 bytes for a  single row.  A 72pt  character (such as in  the
  444.     aminch font) would need  about 430Kb for the  image, but only  about
  445.     200 bytes for a row.
  446.  
  447.     The code  follows  PKtoPX  quite closely,  particular  the  latter's
  448.     sections 37-43  for  preamble  processing, and  sections  44-51  for
  449.     raster decoding.
  450.  
  451.     Access to bit m in the current row is controlled through the  macros
  452.     SETBIT(m) and  TESTBIT(m) so  we  need not  be concerned  about  the
  453.     details of bit masking.  Too bad C does not have a bit data type!
  454.  
  455.     The row image is recorded in such a way that bits min_m .. max_m are
  456.     mapped onto  bits  0  ..  (max_m -  min_m)  in  img_row[],  so  that
  457.     outfcn(c,yoff) should be relieved of any shifting operations.
  458.  
  459.     outfcn(c,yoff) is NEVER called if either of hp or wp is <= 0, or  if
  460.     it is NULL.
  461.     *******************************************************************/
  462.  
  463.    if ((c < FIRSTPXLCHAR) || (LASTPXLCHAR < c))
  464.       {
  465.       (void)warning(
  466.       "charpk():  Character value out of range for PK font file");
  467.       return(EOF);
  468.       }
  469.    tcharptr = &(fontptr->ch[c]);
  470.  
  471.    if (!VISIBLE(tcharptr))
  472.       return(0); /* empty character raster -- nothing to output */
  473.  
  474.    c_width = (unsigned int)tcharptr->wp;    /* local copies of these to save */
  475.    c_height = (unsigned int)tcharptr->hp;  /* pointer dereferencing in loops */
  476.  
  477.    p = (long)tcharptr->fontrp; /* font file raster pointer */
  478.    if (p < 0L)
  479.       {
  480.       (void)warning(
  481.       "charpk():  Requested character not found in PK font file");
  482.       return(EOF);
  483.       }
  484.    if (fseek(fontfp,p,0))
  485.       {
  486.       (void)warning(
  487.       "charpk():  fseek() failure for PK font file character raster");
  488.       return(EOF);
  489.       }
  490.  
  491.    /* Since readpk() has already done error checking on the file, and
  492.     recorded the character metrics, we need not repeat that work, and
  493.     concentrate instead on getting to the encoded raster description
  494.     which follows the character packet.  */
  495.  
  496.    img_words = (unsigned int)(c_width + 31) >> 5;
  497.    flag_byte = (unsigned char)nosignex(fontfp,(unsigned char)1); /* get packet flag byte */
  498.    dyn_f = flag_byte >> 4;    /* dyn_f is high 4 bits from flag_byte */
  499.    turn_on = (unsigned char)(flag_byte & 0x08); /* turn_on is 8-bit from flag_byte */
  500.    flag_byte &= 0x07;        /* final flag_byte is low 3 bits */
  501.    do_output = (int)(outfcn != (void(*)())NULL);
  502.  
  503.    switch(flag_byte)        /* flag_byte is in 0..7 */
  504.       {
  505.    case 0:
  506.    case 1:
  507.    case 2:
  508.    case 3:        /* short character preamble */
  509.       packet_length = (unsigned long int)flag_byte;
  510.       packet_length <<= 8;
  511.       packet_length += (unsigned long int)nosignex(fontfp,(unsigned char)1);
  512.       packet_length -= 8L;
  513.       offset = 9L;
  514.       break;
  515.  
  516.    case 4:
  517.    case 5:
  518.    case 6:        /* extended short character preamble */
  519.       packet_length = (unsigned long int)(flag_byte & 0x03);
  520.       packet_length <<= 16;
  521.       packet_length += (unsigned long int)nosignex(fontfp,(unsigned char)2);
  522.       packet_length -= 13L;
  523.       offset = 14L;
  524.       break;
  525.  
  526.    case 7:        /* long character preamble */
  527.       packet_length = (unsigned long int)nosignex(fontfp,(unsigned char)4);
  528.       packet_length -= 28L;
  529.       offset = 32L;
  530.       break;
  531.  
  532.       } /* end switch */
  533.  
  534.    if (fseek(fontfp,offset,1)) /* position to start of raster data */
  535.       {
  536.       (void)warning(
  537.       "charpk():  fseek() failure for PK font file character raster");
  538.       return(EOF);
  539.       }
  540.  
  541.    bit_weight = 0;
  542.  
  543.    if (dyn_f == (unsigned char)14)    /* <PKtoPX: Get raster by bits> */
  544.       {        /* uncompressed character image */
  545.       for (i = 0; i < c_height; ++i)
  546.          {
  547.          pword = img_row;
  548.          if (do_output)
  549.             (void)clrrow();
  550.          word_weight = (unsigned char)31;
  551.          for (k = 0; k < c_width; ++k)
  552.             {
  553.             if (get_bit())
  554.                *pword |= power[word_weight];
  555.             if (word_weight)
  556.                --word_weight;
  557.             else
  558.                {
  559.                ++pword;
  560.                word_weight = (unsigned char)31;
  561.                }
  562.             } /* end for (k) */
  563.          if (do_output)
  564.             (void)(*outfcn)(c,i);
  565.          } /* end for (i) */
  566.       }
  567.    else    /* <PKtoPX: Create normally packed raster> */
  568.       {    /* run-length encoded character image */
  569.       rows_left = (int)c_height;
  570.       h_bit = c_width;
  571.       repeat_count = 0;
  572.       word_weight = (unsigned char)32;
  573.       pword = img_row;
  574.       if (do_output)
  575.          (void)clrrow();        /* clear img_row[] */
  576.       while (rows_left > 0)
  577.          {
  578.          count = (int)pk_packed_num();
  579.          while (count > 0)
  580.             {
  581.             if ( (count < (int)word_weight) && (count < (int)h_bit) )
  582.                {
  583.                if (turn_on)
  584.                   {
  585.                   *pword |= gpower[word_weight];
  586.                   *pword &= ~gpower[word_weight - count];
  587.                   }
  588.                h_bit -= (unsigned int)count;
  589.                word_weight -= (unsigned char)count;
  590.                count = 0;
  591.                }
  592.             else if ( (count >= (int)h_bit) &&
  593.                (h_bit <= (unsigned int)word_weight) )
  594.                {
  595.                if (turn_on)
  596.                   {
  597.                   *pword |= gpower[word_weight];
  598.                   *pword &= ~gpower[word_weight - h_bit];
  599.                   }
  600.                if (do_output)
  601.                   {
  602.                   for (i = 0; i <= repeat_count; (--rows_left, ++i))
  603.                      (void)(*outfcn)(c,(unsigned int)(c_height-rows_left));
  604.                   }
  605.                else
  606.                   rows_left -= (int)(repeat_count + 1);
  607.                repeat_count = 0;
  608.                pword = img_row;
  609.                if (do_output)
  610.                   (void)clrrow();
  611.                word_weight = (unsigned char)32;
  612.                count -= (int)h_bit;
  613.                h_bit = c_width;
  614.                }
  615.             else
  616.                {
  617.                if (turn_on)
  618.                   *pword |= gpower[word_weight];
  619.                pword++;
  620.                count -= (int)word_weight;
  621.                h_bit -= (unsigned int)word_weight;
  622.                word_weight = (unsigned char)32;
  623.                }
  624.             } /* end while (count > 0) */
  625.          turn_on = (unsigned char)(!turn_on);
  626.          } /* end while (rows_left > 0) */
  627.       if ((rows_left > 0) || (h_bit != c_width))
  628.          {
  629.          (void)warning(
  630.          "charpk():  Bad PK font file--more bits than required");
  631.          return(EOF);
  632.          }
  633.       } /* end if (run-length encoded image) */
  634.  
  635.    return(0);
  636.    }
  637.  
  638. unsigned char get_bit()    /* return 0, or non-zero (not necessarily 1) */
  639.    {
  640.    register unsigned char temp;
  641.  
  642.    bit_weight >>= 1;
  643.    if (bit_weight == 0)    /* then must get new byte from font file */
  644.       {
  645.       next_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
  646.       bit_weight = (unsigned char)128;
  647.       }
  648.    temp = next_byte & bit_weight;
  649.    next_byte &= ~bit_weight;    /* clear the just-read bit */
  650.  
  651.    return (temp);
  652.    }
  653.  
  654. unsigned char get_nybble()
  655.    {
  656.    register unsigned char temp;
  657.  
  658.    if (bit_weight == 0)    /* get high nybble */
  659.       {
  660.       next_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
  661.       temp = next_byte >> 4;
  662.       next_byte &= 0x0f;
  663.       bit_weight = (unsigned char)1;
  664.       }
  665.    else    /* get low nybble */
  666.       {
  667.       temp = next_byte;    /* this has only 4 bits in it */
  668.       bit_weight = (unsigned char)0;
  669.       }
  670.    return(temp);
  671.    }
  672.  
  673. unsigned int pk_packed_num() /* return a (non-negative) packed number from the font file */
  674.    {    /* this function is recursive to one level only */
  675.    int i,j;
  676.  
  677.    i = (int)get_nybble();
  678.    if (i == 0)
  679.       {
  680.       do
  681.          {
  682.          j = (int)get_nybble();
  683.          ++i;
  684.          } 
  685.       while (j == 0);
  686.       while (i > 0)
  687.          {
  688.          j <<= 4;
  689.          j += (int)get_nybble();
  690.          --i;
  691.          }
  692.       return((unsigned int)(j - 15 + ((13 - dyn_f) << 4) + dyn_f));
  693.       }
  694.    else if (i <= (int)dyn_f)
  695.       return((unsigned int)i);
  696.    else if (i < 14)
  697.       return((unsigned int)(((i - dyn_f - 1) << 4) + get_nybble() + dyn_f + 1));
  698.    else if (i == 14)
  699.       {
  700.       repeat_count = pk_packed_num();
  701.       return(pk_packed_num());
  702.       }
  703.    else
  704.       {
  705.       repeat_count = 1;
  706.       return(pk_packed_num());
  707.       }
  708.    }
  709.  
  710. int charpxl(c,outfcn)    /* return 0 on success, and EOF on failure */
  711. unsigned char c;            /* current character value */
  712. void (*outfcn)();    /* (possibly NULL) function to output current row */
  713.    {
  714.    unsigned int i,j;        /* loop index */
  715.    long p;            /* offset into font file */
  716.    register unsigned long int *q;    /* pointer into rasters area */
  717.    struct char_entry *tcharptr;/* temporary char_entry pointer */
  718.  
  719.    if ((c < FIRSTPXLCHAR) || (LASTPXLCHAR < c))
  720.       {
  721.       (void)warning(
  722.       "charpxl():  Character value out of range for PXL font file");
  723.       return(EOF);
  724.       }
  725.    tcharptr = &(fontptr->ch[c]);
  726.  
  727.    if (!VISIBLE(tcharptr))
  728.       return(0);    /* do nothing for empty characters */
  729.  
  730.    p = (long)tcharptr->fontrp;    /* font file raster pointer */
  731.    if (p < 0L)
  732.       {
  733.       (void)warning(
  734.       "charpxl():  Requested character not found in PXL font file");
  735.       return(EOF);
  736.       }
  737.  
  738.    if (fseek(fontfp,p,0))
  739.       {
  740.       (void)warning(
  741.       "charpxl():  fseek() failure for PXL font file character raster");
  742.       return(EOF);
  743.       }
  744.  
  745.    if (outfcn != (void(*)())NULL)
  746.       {
  747.       img_words = ((unsigned int)(tcharptr->wp) + 31) >> 5;
  748.       for (i = 0; i < (unsigned int)(tcharptr->hp); ++i)
  749.          {
  750.          q = img_row;
  751.          for (j = 0; j < img_words; ++j)
  752.             *q++ = (unsigned long int)nosignex(fontfp,(unsigned char)4);
  753.          (void)(*outfcn)(c,i);
  754.          }
  755.       }
  756.    return(0);
  757.    }
  758.  
  759. void clrrow()    /* clear the current character image row, img_row[] */
  760.    {
  761.    register unsigned long int *p;
  762.    register unsigned int nwords;
  763.  
  764.    nwords = img_words;
  765.    for (p = &img_row[nwords-1]; nwords; (--p,--nwords))
  766.       *p = (unsigned long int)0L;
  767.    }
  768.  
  769.  
  770. void fillrect(x,y,width,height)
  771. int x,y,width,height;        /* lower left corner, size */
  772.  
  773. /***********************************************************************
  774. With the page origin (0,0) at the lower-left corner of the bitmap,  draw
  775. a filled rectangle at (x,y).
  776. ***********************************************************************/
  777.  
  778.    {
  779.    register unsigned long int *p;
  780.    register int i,j,xloffset,xroffset,xlpart,xrpart;
  781.  
  782.    if ( ((x+width) <= 0) || (XSIZE <= x) || ((y+height) <= 0) ||
  783.       (YSIZE <= y) )
  784.       return;        /* Trivial reject -- rectangle outside page */
  785.    else
  786.       {
  787.       xlpart = x/32;
  788.       xrpart = (x + width)/32;
  789.       xloffset = x % 32;
  790.       xroffset = (x + width) % 32;
  791.       for (j = 0; j < height; ++j)        /* loop over raster lines */
  792.          {
  793.          if (IN(0,y+j,YBIT-1))
  794.             {
  795.             p = rd_bitmap(y+j,xlpart);
  796.             if (IN(0,xlpart,XBIT-1))
  797.                if (xlpart < xrpart) /* set bits in left partial word */
  798.                   *p |= rightones[xloffset];
  799.                else    /* set bits in middle of left partial word */
  800.                *p |= (rightones[xloffset] & ~rightones[xroffset]);
  801.  
  802.             ++p;
  803.             for (i = xlpart+1; i < xrpart; (++p,++i))
  804.                if (IN(0,i,XBIT-1))
  805.                   *p = (unsigned long int)ONES;  /* set complete words */
  806.  
  807.             /* finally, set bits in right partial word */
  808.             if ((xlpart < xrpart) && IN(0,xrpart,XBIT-1))
  809.                *rd_bitmap(y+j,xrpart) |= ~rightones[xroffset];
  810.             }
  811.          }
  812.       }
  813.    }
  814.  
  815.  
  816. void fontfile(filelist,font_path,font_name,magnification)
  817. char *filelist[MAXFORMATS];    /* output filename list */
  818. char *font_path;        /* host font file pathname */
  819. char *font_name;        /* TeX font_name */
  820. int magnification;        /* magnification value */
  821.    {
  822.  
  823.    /*
  824.     Given a TeX font_name and a magnification value, construct a list of
  825.     system-dependent  host  filenames,  returning  them  in  the   first
  826.     argument.  The files are not guaranteed to exist.  The font names by
  827.     default contains names for the PK,  GF, and PXL font files, but  the
  828.     selection, and search order, may be changed at run time by  defining
  829.     a value for the environment  variable FONTLIST.  See initglob()  for
  830.     details.
  831.     */
  832.  
  833.    register int m;            /* index into filelist[] */
  834.    register int k;            /* loop index */
  835.    double fltdpi;            /* dots/inch */
  836.    int dpi;                /* dots/inch for filename */
  837.  
  838.    /*
  839.     We need to convert an old-style ROUNDED integer magnification based
  840.     on 1000 units = 200 dpi to an actual rounded dpi value.
  841.  
  842.     We have
  843.     magnification = round(real_mag) = trunc(real_mag + 0.5)
  844.     which implies
  845.     double(magnification) - 0.5 <= real_mag < double(magnification) + 0.5
  846.  
  847.     We want
  848.     dpi = round(real_mag/5.0)
  849.     which implies
  850.     double(dpi) - 0.5 <= real_mag/5.0 < double(dpi) + 0.5
  851.     or
  852.     5.0*double(dpi) - 2.5 <= real_mag < 5.0*double(dpi) + 2.5
  853.  
  854.     We can combine the two to conclude that
  855.     5.0*double(dpi) - 2.5 < double(magnification) + 0.5
  856.     or
  857.     5.0*double(dpi) - 3 < double(magnification)
  858.     which gives the STRICT inequality
  859.     double(dpi) < (double(magnification) + 3.0)/5.0
  860.     */
  861.  
  862.    fltdpi = (((double)magnification) + 3.0)/5.0;
  863.    dpi = (int)fltdpi;
  864.    if (fltdpi == (double)dpi)
  865.       dpi--;                /* enforce inequality */
  866.  
  867.    for (k = 0; k < MAXFORMATS; ++k) /* loop over possible file types */
  868.       *filelist[k] = '\0';    /* Initially, all filenames are empty */
  869.  
  870.    m = 0;                /* index in filelist[] */
  871.    for (k = 0; k < MAXFORMATS; ++k) /* loop over possible file types */
  872.       {
  873.  
  874.  
  875.       /* Typical results:
  876.         d:\tex\fonts\300\amr10.gf
  877.         d:\tex\fonts\300\amr10.pk
  878.         d:\tex\fonts\1500\amr10.pxl
  879.     */
  880.  
  881.       if (k == gf_index)
  882.          (void)sprintf(filelist[m++], "%s%d\\%s.gf",
  883.          font_path, dpi, font_name);
  884.       else if (k == pk_index)
  885.          (void)sprintf(filelist[m++], "%s%d\\%s.pk",
  886.          font_path, dpi, font_name);
  887.       else if (k == pxl_index)
  888.          (void)sprintf(filelist[m++], "%s%d\\%s.pxl",
  889.          font_path, magnification, font_name);
  890.       }
  891.    }
  892.  
  893. /***********************************************************************
  894.  
  895. Given a  TeX  fontname  and  a  magnification  value,  search  the  font
  896. substitution file (if  any) for  the first pattern  defining a  possible
  897. replacement, and return  their values  in subfont[] and  submag, with  a
  898. function value of TRUE.   If no substitution  is possible, subfont[]  is
  899. set to a null string, submag to 0, and the function value to FALSE.
  900.  
  901. The substitution file is searched for under the names
  902.  
  903.     (1) subfile (by default, or from command line)
  904.     (2) subname subext
  905.     (3) subpath subname subext
  906.  
  907. allowing the user to have document-file specific substitutions, TeX-wide
  908. private substitutions, and system TeX-wide substitutions.  For  example,
  909. these     files      might    be     "sample.sub",      "texfonts.sub",    and
  910. "texinputs:texfonts.sub" for a document "sample.tex".
  911.  
  912. Font substitution lines have the form:
  913.  
  914. % comment
  915. oldname.oldmag    ->    subname.submag    % comment
  916. oldname oldmag    ->    subname submag    % comment
  917. oldname     ->    subname        % comment
  918.  
  919. Examples are:
  920.  
  921. % These provide replacements for some LaTeX invisible fonts:
  922. iamr10 1500    ->    amr10 1500    % comment
  923. iamr10.1500    ->    amr10.1500    % comment
  924. iamssb8        ->    amssb8        % comment
  925.  
  926. These are  easily readable  by sscanf().   The first  two forms  request
  927. substitution of a  particular font  and magnification.     The third  form
  928. substitutes an entire font  family; the closest available  magnification
  929. to the required one will be  used.  Any dots in the non-comment  portion
  930. will be converted  to spaces, and  therefore, cannot be  part of a  name
  931. field.
  932.  
  933. The first  matching substitution  will  be selected,  so  magnification-
  934. specific  substitutions   should   be    given    first,     before   family
  935. substitutions.
  936.  
  937. Comments are introduced by percent and continue to end-of-line, just  as
  938. for TeX.   One  whitespace character  is  equivalent to  any  amount  of
  939. whitespace.  Whitespace and comments are optional.
  940. ***********************************************************************/
  941.  
  942.  
  943. int fontsub(subfont,submag,TeXfont,TeXmag)
  944. char *subfont;        /* new fontname returned */
  945. int  *submag;        /* new magnification returned (0 if entire family) */
  946. char *TeXfont;        /* TeX requested fontname */
  947. int TeXmag;        /* TeX requested magnification value */
  948.    {
  949.    static FILE* subfp = (FILE *)NULL;    /* file pointer for sub file */
  950.    static int have_file = TRUE;    /* memory of open success */
  951.    char line[MAXSTR];            /* for sub file lines */
  952.    char *pline;            /* pointer to line[] */
  953.    static char fname[64];    /* sub file name */
  954.    char oldfont[64];        /* working storage for font names */
  955.    int oldmag;                /* font magnification */
  956.    int k;                /* sscanf() result */
  957.    int line_number;            /* for error messages */
  958.  
  959.    if (!have_file)            /* no file available */
  960.       {
  961.       *subfont = '\0';
  962.       *submag = 0;
  963.       return (FALSE);
  964.       }
  965.    else if (subfp == (FILE *)NULL)    /* happens only first time  */
  966.       {
  967.       (void)strcpy(fname,subfile);    /* try document specific: */
  968.       subfp = fopen(fname,"r");    /* e.g. foo.sub (from foo.dvi) */
  969.       DEBUG_OPEN(subfp,fname,"r");
  970.       if (subfp == (FILE *)NULL)
  971.          {
  972.          (void)strcpy(fname,subname);/* try path specific: */
  973.          (void)strcat(fname,subext);    /* e.g. texfonts.sub */
  974.          subfp = fopen(fname,"r");
  975.          DEBUG_OPEN(subfp,fname,"r");
  976.          }
  977.  
  978.       if (subfp == (FILE *)NULL)
  979.          {
  980.          (void)strcpy(fname,subpath);/* try system specific: */
  981.          (void)strcat(fname,subname);/* e.g. texinputs:texfonts.sub */
  982.          (void)strcat(fname,subext);
  983.          subfp = fopen(fname,"r");
  984.          DEBUG_OPEN(subfp,fname,"r");
  985.          }
  986.  
  987.       if (subfp == (FILE *)NULL) /* could not open any substitution file */
  988.          {
  989.          have_file = FALSE;
  990.          *subfont = '\0';
  991.          *submag = 0;
  992.          return (FALSE);
  993.          }
  994.       }
  995.  
  996.    line_number = 0;
  997.    (void)rewind(subfp);
  998.    while (fgets(line,MAXSTR,subfp) != (char *)NULL)
  999.       {
  1000.       line_number++;        /* count lines */
  1001.  
  1002.       pline = &line[0];    /* truncate at comment start or end-of-line */
  1003.       while ((*pline) && (*pline != '%') &&
  1004.          (*pline != '\r') && (*pline != '\n'))
  1005.          {
  1006.          if (*pline == '.')    /* convert dots to whitespace for sscanf() */
  1007.             *pline = ' ';
  1008.          ++pline;
  1009.          }
  1010.       *pline = '\0';        /* replace terminator by NUL */
  1011.  
  1012.       if ((k = (int)sscanf(line," %s %d -> %s %d",oldfont,&oldmag,
  1013.       subfont,submag)) == 4)
  1014.          {
  1015.          if ((TeXmag == oldmag) && (stricmp(oldfont,TeXfont) == 0))
  1016.             return (TRUE);
  1017.          }
  1018.       else if ((k = (int)sscanf(line," %s -> %s",oldfont,subfont)) == 2)
  1019.          {
  1020.          *submag = 0;
  1021.          if (stricmp(oldfont,TeXfont) == 0)
  1022.             return (TRUE);
  1023.          }
  1024.       else if (k != EOF)    /* EOF means no fields, so have empty line */
  1025.          {
  1026.          (void)sprintf(message,
  1027.          "fontsub():  Bad font substitution at line %d in file \
  1028. [%s]: [%s]",
  1029.          line_number,fname,line);
  1030.          (void)warning(message);
  1031.          }
  1032.       }
  1033.    *subfont = '\0';
  1034.    *submag = 0;
  1035.    return (FALSE);
  1036.    }
  1037.  
  1038. /***********************************************************************
  1039. Read the font definitions as they are in the postamble of the DVI  file.
  1040. Note that the font directory is not yet loaded.
  1041. ***********************************************************************/
  1042.  
  1043. void getfntdf()
  1044.    {
  1045.    register unsigned char    byte;
  1046.  
  1047.    while (((byte = (unsigned char)nosignex(dvifp,(unsigned char)1)) >= FNT_DEF1)
  1048.       && (byte <= FNT_DEF4))
  1049.       readfont ((long int)nosignex(dvifp,(unsigned char)(byte-FNT_DEF1+1)));
  1050.    if (byte != POST_POST)
  1051.       (void)fatal ("getfntdf():  POST_POST missing after fontdefs");
  1052.    }
  1053.  
  1054. void getpgtab(lastpageptr)
  1055. long lastpageptr;
  1056.  
  1057.    {
  1058.    register long p;
  1059.    register int i,k;
  1060.  
  1061.    (void) fseek (dvifp,lastpageptr,0);
  1062.    p = lastpageptr;
  1063.  
  1064.    for (k = 0; (p != (-1)) && (k < MAXPAGE); ++k)
  1065.       {
  1066.       page_ptr[MAXPAGE-1-k] = p;
  1067.       (void) fseek (dvifp,(long) p, 0);
  1068.  
  1069.       if ((unsigned char)nosignex(dvifp,(unsigned char)1) != BOP)
  1070.          (void)fatal(
  1071.          "getpgtab():  Invalid BOP (beginning-of-page) back chain");
  1072.  
  1073.       for (i = 0; i <= 9; ++i)
  1074.          (void) nosignex(dvifp,(unsigned char)4);   /* discard count0..count9 */
  1075.       p = (long)signex(dvifp,(unsigned char)4);
  1076.       }
  1077.    page_count = k;
  1078.    if (k >= MAXPAGE)
  1079.       (void)warning("getpgtab():  Page table full...rebuild driver with \
  1080. larger MAXPAGE");
  1081.    else    /* move pointer table to front of array */
  1082.       for (k = 0; k < page_count; ++k)
  1083.          page_ptr[k] = page_ptr[MAXPAGE-page_count+k];
  1084.    }
  1085.  
  1086. /***********************************************************************
  1087. Convert a value field in s[] of the form
  1088.  
  1089.     ------        ------------------------------
  1090.     value            units implied
  1091.     ------        ------------------------------
  1092.     #.##bp        big point (1in = 72bp)
  1093.     #.##cc        cicero (1cc = 12dd)
  1094.     #.##cm        centimeter
  1095.     #.##dd        didot point (1157dd = 1238pt)
  1096.     #.##in        inch
  1097.     #.##mm        millimeter (10mm = 1cm)
  1098.     #.##pc        pica (1pc = 12pt)
  1099.     #.##pt        point (72.27pt = 1in)
  1100.     #.##sp        scaled point (65536sp = 1pt)
  1101.     ------        ------------------------------
  1102.  
  1103. to inches, returning it as the function value.  A leading plus or  minus
  1104. sign is optional.  The letter case of the dimension name is ignored.  No
  1105. space is permitted between the number and the dimension.
  1106. ***********************************************************************/
  1107.  
  1108. double inch(char *s)
  1109.    {
  1110.    int neg;
  1111.    register char *tc;
  1112.    register double flnum, pten;
  1113.  
  1114.    flnum = 0.0;
  1115.    tc = s;
  1116.    neg = FALSE;
  1117.  
  1118.    if (*tc == '-')
  1119.       {
  1120.       ++tc;
  1121.       neg = TRUE;
  1122.       }
  1123.    else if (*tc == '+')
  1124.       {
  1125.       ++tc;
  1126.       neg = FALSE;
  1127.       }
  1128.  
  1129.    /* we do not use sprintf() here because we want to be able to easily
  1130.     find the dimension string */
  1131.  
  1132.    for (; isdigit(*tc); ++tc)    /* collect integer part */
  1133.       flnum = flnum*10.0 + (double)((*tc) - '0');
  1134.  
  1135.    if (*tc == '.')            /* collect fractional part */
  1136.       for ((pten = 10.0, ++tc); isdigit(*tc); (pten *= 10.0,++tc))
  1137.          flnum += ((double)((*tc) - '0'))/pten;
  1138.  
  1139.    if (stricmp(tc,"in") == 0)        /* inches */
  1140.       ;
  1141.    else if (stricmp(tc,"cm") == 0)    /* centimeters */
  1142.       flnum /= 2.54;
  1143.    else if (stricmp(tc,"pt") == 0)    /* points */
  1144.       flnum /= 72.27;
  1145.    else if (stricmp(tc,"bp") == 0)    /* big points */
  1146.       flnum /= 72.0;
  1147.    else if (stricmp(tc,"cc") == 0)    /* cicero */
  1148.       flnum *= 12.0 * (1238.0 / 1157.0) / 72.27;
  1149.    else if (stricmp(tc,"dd") == 0)    /* didot points */
  1150.       flnum *= (1238.0 / 1157.0) / 72.27;
  1151.    else if (stricmp(tc,"mm") == 0)    /* millimeters */
  1152.       flnum /= 25.4;
  1153.    else if (stricmp(tc,"pc") == 0)    /* pica */
  1154.       flnum *= 12.0 / 72.27;
  1155.    else if (stricmp(tc,"sp") == 0)    /* scaled points */
  1156.       flnum /= (65536.0 * 72.27);
  1157.    else                /* unknown units -- error */
  1158.  
  1159. #if    PXLID                            /* must be in DVI driver */
  1160.       {
  1161.       (void)sprintf(message,
  1162.       "inch():  Unrecognized dimension string [%s];\nexpected one of \
  1163. bp, cc, cm, dd, in, mm, pc, pt or sp\n",s);
  1164.       (void)fatal(message);
  1165.       }
  1166. #else                                   /* some other program then */
  1167.       {
  1168.       (void)fprintf(stderr,"inch():  Unrecognized dimension string [%s];",s);
  1169.       NEWLINE(stderr);
  1170.       (void)fprintf(stderr,
  1171.       "expected one of bp, cc, cm, dd, in, mm, pc, pt or sp");
  1172.       NEWLINE(stderr);
  1173.       exit(1);
  1174.       }
  1175. #endif
  1176.  
  1177.    if (neg)
  1178.       flnum = -flnum;
  1179.    return((double)flnum);
  1180.    }
  1181.  
  1182. /***********************************************************************
  1183.     This simple version will do for now.  Even in a book DVI file, there
  1184.     are unlikely to be more than about 25 fonts used and with an average
  1185.     of 50 characters  each, this  is about  1250 character  definitions.
  1186.     With typical character  sizes of 10  point type on  a 300  dots/inch
  1187.     device, each would take a block of (10/72)*300 = 42 dots square,  or
  1188.     about 84 words each,  for a total storage  requirement of 84*1250  =
  1189.     105000 words.  This is  quite reasonable for  the DEC-20/60 and  VAX
  1190.     Unix  implementations,  and  may  be  acceptable  on  large   memory
  1191.     microprocessors like the MC68000 and NS16000.
  1192.  
  1193.     However, for future expansion, a  reference count of each  character
  1194.     is  maintained,  and  the  total  storage  allocated  for  character
  1195.     descriptions is recorded.  Then, when  malloc fails, or MAXCACHE  is
  1196.     reached, the font  entries can  be scanned  to find  the least  used
  1197.     characters whose  raster  storage  can  then  be  freed  and  malloc
  1198.     retried.
  1199. ***********************************************************************/
  1200.  
  1201.  
  1202. void loadchar(unsigned char c)
  1203.    {
  1204.    void (*charyy)();        /* subterfuge to get around PCC-20 bug */
  1205.    register unsigned long int nwords;    /* how many 32-bit words we need */
  1206.    register struct char_entry *tcharptr;
  1207.  
  1208.    if ((c < FIRSTPXLCHAR) || (LASTPXLCHAR < c)) /* check character range */
  1209.       return;
  1210.  
  1211.    tcharptr = &(fontptr->ch[c]);
  1212.  
  1213.    if (!VISIBLE(tcharptr))    /* check for empty character rasters */
  1214.       return;
  1215.  
  1216.    nwords = (unsigned long int)(((tcharptr->wp+31) >> 5) * (tcharptr->hp));
  1217.  
  1218.    tcharptr->rasters = (unsigned long int*)malloc((unsigned)(nwords*sizeof(unsigned long int)));
  1219.    if (tcharptr->rasters == (unsigned long int*)NULL)
  1220.       {
  1221.       (void)sprintf(message,"loadchar():  Could not allocate %ld words of \
  1222. raster space--used %ld words so far",
  1223.       (long)nwords,(long)cache_size);
  1224.       (void)fatal(message);
  1225.       }
  1226.    tcharptr->refcount = 0;        /* clear reference count */
  1227.    cache_size += (long int)nwords;    /* update cache size record */
  1228.  
  1229.    if (fontptr != pfontptr)
  1230.       openfont(fontptr->n);
  1231.  
  1232.    if (fontfp == (FILE *)NULL)        /* do nothing if no font file */
  1233.       return;
  1234.  
  1235.    /* Bug workaround: PCC-20 otherwise jumps to charxx instead of *charxx */
  1236.    charyy = fontptr->charxx;
  1237.    (void)(*charyy)(c,outrow);        /* load character from font file */
  1238.    }
  1239.  
  1240. /*    From DVITYPE Version 2.6:
  1241.     "Vertical motion is done similarly [to horizontal motion handled
  1242.     in moveover()],  but with  the threshold  between ``small''  and
  1243.     ``large'' increased by  a factor of  five. The idea  is to  make
  1244.     fractions  like  ``1/2''  round  consistently,  but  to   absorb
  1245.     accumulated rounding errors in the baseline-skip moves."
  1246.  
  1247.     The one precaution we need to  take here is that fontptr can  be
  1248.     NULL, which we treat like  a large movement.  This NULL  pointer
  1249.     was used without error  on many different  machines for 2  years
  1250.     before it was caught on the VAX VMS implementation, which  makes
  1251.     memory page 0 inaccessible.
  1252.     */
  1253.  
  1254. void movedown(a)
  1255. register long int a;
  1256.  
  1257.    {
  1258.    v += a;
  1259.    if ((fontptr == (struct font_entry *)NULL) ||
  1260.       (ABS(a) >= 5*fontptr->font_space))
  1261.       vv = PIXROUND(v, conv  * ((double)YDPI/(double)XDPI)) + tmargin;
  1262.    else
  1263.       {
  1264.       vv += PIXROUND(a, conv  * ((double)YDPI/(double)XDPI));
  1265.       vv = fixpos(vv-tmargin, v,
  1266.             conv * ((double)YDPI/(double)XDPI)) + tmargin;
  1267.       }
  1268.    }
  1269.  
  1270.  
  1271. /*    From DVITYPE Version 2.6:
  1272.     "Rounding to the nearest pixel is  best done in the manner shown
  1273.     here, so as to  be inoffensive to the  eye: When the  horizontal
  1274.     motion is small, like a kern, |hh| changes by rounding the kern;
  1275.     but when the motion is large, |hh| changes by rounding the  true
  1276.     position |h| so that  accumulated rounding errors disappear.  We
  1277.     allow a  larger space  in  the negative  direction than  in  the
  1278.     positive one, because TeX  makes comparatively large  backspaces
  1279.     when it positions accents."
  1280.  
  1281.     The one precaution we need to  take here is that fontptr can  be
  1282.     NULL, which we treat like  a large movement.  This NULL  pointer
  1283.     was used without error  on many different  machines for 2  years
  1284.     before it was caught on the VAX VMS implementation, which  makes
  1285.     memory page 0 inaccessible.
  1286.     */
  1287.  
  1288. void moveover(b)
  1289. register long int b;
  1290.    {
  1291.    h += b;
  1292.    if ((fontptr == (struct font_entry *)NULL) ||
  1293.       ABS(b) >= fontptr->font_space)
  1294.       hh = PIXROUND(h, conv) + lmargin;
  1295.    else
  1296.       {
  1297.       hh += PIXROUND(b, conv);
  1298.       hh = fixpos(hh-lmargin,h,conv) + lmargin;
  1299.       }
  1300.    }
  1301.  
  1302. void moveto(x,y)
  1303. int x,y;
  1304.    {
  1305.    xcp = x;
  1306.    ycp = y;
  1307.    }
  1308.  
  1309.  
  1310.  
  1311. unsigned long int nosignex(fp, n)    /* return n byte quantity from file fd */
  1312. register FILE *fp;    /* file pointer    */
  1313. register unsigned char n;    /* number of bytes (1..4) */
  1314.  
  1315.    {
  1316.    register unsigned long int number;    /* number being constructed */
  1317.  
  1318.    number = 0;
  1319.    while (n--)
  1320.       {
  1321.       number <<= 8;
  1322.       number |= getc(fp);
  1323.       }
  1324.    return((unsigned long int)number);
  1325.    }
  1326.  
  1327.  
  1328. /***********************************************************************
  1329.     The original version of this DVI driver reopened the font file  each
  1330.     time the font changed, resulting in an enormous number of relatively
  1331.     expensive file  openings.    This version  keeps  a cache  of  up  to
  1332.     MAXOPEN open files,  so that when  a font change  is made, the  file
  1333.     pointer, fontfp, can  usually be  updated from the  cache.  When the
  1334.     file is not found in  the cache, it must  be opened.  In this  case,
  1335.     the next empty slot  in the cache  is assigned, or  if the cache  is
  1336.     full, the least used font file is closed and its slot reassigned for
  1337.     the new file.  Identification of the least used file is based on the
  1338.     counts of the number  of times each file  has been "opened" by  this
  1339.     routine.  On return, the file pointer is always repositioned to  the
  1340.     beginning of the file.
  1341.  
  1342.     If the first open attempt  fails, an attempt will  be made to use  a
  1343.     substitute font, then neighboring magnifications (with the same font
  1344.     name), or substitutes for them.
  1345. ***********************************************************************/
  1346.  
  1347.  
  1348. void openfont(fontname)
  1349. char *fontname;
  1350.    {
  1351.    register int i,j,k;    /* loop indices */
  1352.    int current;
  1353.    int least_used;
  1354.    int maxopen = MAXOPEN;
  1355.  
  1356.    struct font_entry *tfontptr;
  1357.    char subfont[64];
  1358.    int submag;
  1359.    char* filelist[MAXFORMATS];    /* pointers to templist[][] */
  1360.    char templist[MAXFORMATS][64];
  1361.  
  1362. #if    VIRTUAL_FONTS
  1363.  
  1364.    struct stat statbuf;        /* so fstat() can get file size */
  1365.    char *p;
  1366. #endif
  1367.    if ((pfontptr != (struct font_entry *)NULL) && (pfontptr == fontptr))
  1368.       return;            /* we need not have been called */
  1369.  
  1370.    for (j = 0; j < MAXFORMATS; ++j)    /* initialize fontlist pointers */
  1371.       filelist[j] = &templist[j][0];
  1372.  
  1373.    for (current = 1;
  1374.     (current <= nopen) &&
  1375.         (font_files[current].font_id != fontptr->font_file_id);
  1376.     ++current)
  1377.          ;            /* try to find file in open list */
  1378.  
  1379.    if (current <= nopen)    /* file already open, lookup its id */
  1380.       fontfp = font_files[current].font_id;
  1381.    else
  1382.       {
  1383.       /***************************************************************
  1384.     The file was  not in list  of open  files.  If the  list is  not
  1385.     full, add it to  the list; otherwise  close the least-used  file
  1386.     and remove it from the font_entry containing it.  Finally,  open
  1387.     the file, or its closest  neighbor in the magnification  family.
  1388.     A warning is issued  if no file can  be opened.  The caller  can
  1389.     then proceed with zero font metrics if desired.
  1390.     ***************************************************************/
  1391.  
  1392.  
  1393.       if (nopen < maxopen)    /* just add it to list */
  1394.          current = ++nopen;
  1395.       else            /* list full -- find least used file, */
  1396.          {            /* close it, and reuse slot for new file */
  1397.          least_used = 1;
  1398.          for (i = 2; i <= maxopen; ++i)
  1399.             if (font_files[least_used].use_count >
  1400.                font_files[i].use_count)
  1401.                least_used = i;
  1402.  
  1403.          fontfp = font_files[least_used].font_id;
  1404.          tfontptr = hfontptr;
  1405.          while (tfontptr != (struct font_entry*)NULL)
  1406.             {            /* remove file pointer from its font_entry */
  1407.             if (tfontptr->font_file_id == fontfp)
  1408.                {
  1409.                tfontptr->font_file_id = (FILE*)NULL;
  1410.                break;
  1411.                }
  1412.             tfontptr = tfontptr->next;
  1413.             }
  1414. #if    VIRTUAL_FONTS
  1415.          if (virt_font && (fontfp != (FILE*)NULL))
  1416.             (void)virtfree(fontfp);
  1417. #endif
  1418.          (void)fclose(fontfp);
  1419.          fontfp = (FILE*)NULL;
  1420.          current = least_used;
  1421.          }
  1422.       (void)actfact(fontptr->font_mag);    /* Get global mag_index */
  1423.  
  1424.       fontfp = (FILE*)NULL;
  1425.  
  1426.       /***************************************************************
  1427.     Try the requested font, then any substitute font, then for  each
  1428.     neighboring magnification  from  nearest to  furthest,  try  the
  1429.     requested font, and then any substitute font.
  1430.     ***************************************************************/
  1431.  
  1432.       for (k = 0; (fontfp == (FILE*)NULL) && (k < MAGTABSIZE); ++k)
  1433.          {                /* loop over mag family */
  1434.          for (i = -k; (fontfp == (FILE*)NULL) && (i <= k); i += MAX(1,k+k))
  1435.             {                /* try smaller, then larger */
  1436.             if (IN(0,mag_index+i,MAGTABSIZE-1))
  1437.                {
  1438.                (void)fontfile(filelist, ((fontptr->a==0)?fontpath:""),
  1439.                fontname, (int)MAGSIZE(mag_table[mag_index+i]));
  1440.                for (j = 0; (j < MAXFORMATS) && *filelist[j]; ++j)
  1441.                   {
  1442.                   fontfp = fopen(filelist[j],"rb");
  1443.                   DEBUG_OPEN(fontfp,filelist[j],"rb");
  1444.                   if (fontfp != (FILE *)NULL)
  1445.                      {
  1446.                      strcpy(fontptr->name,filelist[j]);
  1447.                      break;
  1448.                      }
  1449.                   }
  1450.                if ((k > 0) && (fontfp != (FILE*)NULL))
  1451.                   {
  1452.                   (void)sprintf(message,
  1453.                   "Font file [%s [mag %d]] could not be opened.\n\
  1454. ---using nearest neighbor [%s [mag %d]] instead.",
  1455.                   fontname,(int)MAGSIZE(mag_table[mag_index]),
  1456.                   fontptr->name,
  1457.                   (int)MAGSIZE(mag_table[mag_index+i]));
  1458.                   (void)warning(message);
  1459.                   }
  1460.  
  1461.                if ((fontfp == (FILE*)NULL) && fontsub(subfont,&submag,
  1462.                fontname,(int)MAGSIZE(mag_table[mag_index+i])))
  1463.                   {
  1464.                   (void)fontfile(filelist,((fontptr->a==0)?fontpath:""),
  1465.                   subfont,(submag ? submag :
  1466.                   (int)MAGSIZE(mag_table[mag_index+i])));
  1467.                   for (j = 0; (j < MAXFORMATS) && *filelist[j]; ++j)
  1468.                      {
  1469.                      fontfp = fopen(filelist[j],"rb");
  1470.                      DEBUG_OPEN(fontfp,filelist[j],"rb");
  1471.                      if (fontfp != (FILE *)NULL)
  1472.                         {
  1473.                         strcpy(fontptr->name,filelist[j]);
  1474.                         break;
  1475.                         }
  1476.                      }
  1477.  
  1478.                   if (fontfp != (FILE*)NULL)
  1479.                      {
  1480.                      (void)sprintf(message,
  1481.                      "Substituting font file [%s [mag %d]] \
  1482. by [%s [mag %d]]",
  1483.                      fontname,(int)MAGSIZE(mag_table[mag_index]),
  1484.                      fontptr->name,
  1485.                      (int)MAGSIZE(mag_table[mag_index+i]));
  1486.                      (void)warning(message);
  1487.                      }
  1488.                   }
  1489.                }
  1490.             } /* end for (i) -- loop over smaller and larger neighbors  */
  1491.          } /* end for (k) -- loop over mag family */
  1492.  
  1493.       if (fontfp == (FILE*)NULL)
  1494.          {
  1495.          --nopen;            /* don't count this failed open */
  1496.          (void)sprintf(message,"Font file [%s [mag %d]] could not be \
  1497. opened; %d font files are open\n\
  1498. Proceeding with zero size characters for this font",
  1499.          fontname,(int)MAGSIZE(mag_table[mag_index]),nopen);
  1500.          (void)warning(message);
  1501.          }
  1502.  
  1503.       font_files[current].font_id = fontfp;
  1504.       font_files[current].use_count = 0;
  1505.  
  1506. #if    VIRTUAL_FONTS
  1507.  
  1508.       /*
  1509.     ****************************************************************
  1510.     This code  is implementation-dependent.   On many  C  compilers,
  1511.     FILE points to a struct of the form
  1512.  
  1513.     struct    _iobuf {
  1514.         char    *_ptr;    // pointer to next available char
  1515.         int    _cnt;    // number of chars left in buffer
  1516.         char    *_base;    // pointer to start of buffer
  1517.         int    _flag;    // assorted flags
  1518.         int    _file;    // file number handle
  1519.         }
  1520.  
  1521.     To implement virtual fonts,  we save the  pointers in a  private
  1522.     global array, get the file size from fstat(), malloc() a  buffer
  1523.     for it, read the entire file in, and replace the pointers in the
  1524.     FILE variable with ones  for  the  new buffer.  Just before  the
  1525.     file is  closed, the space is  freed  and the   old pointers are
  1526.     restored.   Although many C implementations use  malloc() to get
  1527.     the buffer  space  in the  first place, which  would  make  this
  1528.     saving unnecessary, not all do; see  the implementation given in
  1529.     Kernighan and Ritchie "The C Programming Language", p. 168.
  1530.  
  1531.     In  implementing   this   code   on   any   new   machine,   the
  1532.     implementations of fread(), read(), fseek(), and rewind() should
  1533.     be checked to  choose the  most efficient one  (e.g. one  system
  1534.     call for entire file  read, and no  double buffering), and  make
  1535.     sure that  fseek() and  rewind()  do not  unnecessarily  discard
  1536.     input buffer  contents.  fseek()  and  rewind() are  defined  in
  1537.     terms of macros FSEEK() and REWIND() in machdefs.h to facilitate
  1538.     replacement.
  1539.     ****************************************************************
  1540.     */
  1541.       if (virt_font)
  1542.          {
  1543.          virt_save[fileno(fontfp)].base = (char *)NULL;
  1544.          (void)fstat(fileno(fontfp),&statbuf);    /* get file size */
  1545.          p = (char *)malloc((int)statbuf.st_size);    /* get file buffer */
  1546.          if (p != (char *)NULL)
  1547.             {
  1548.             if (read(fileno(fontfp),p,(int)statbuf.st_size)
  1549.                == (int)statbuf.st_size)
  1550.                {            /* read successful */
  1551.                virt_save[fileno(fontfp)].ptr = FILE_PTR(fontfp);
  1552.                virt_save[fileno(fontfp)].cnt = FILE_CNT(fontfp);
  1553.                virt_save[fileno(fontfp)].base = FILE_BASE(fontfp);
  1554.                FILE_PTR(fontfp) = p;
  1555.                FILE_BASE(fontfp) = p;
  1556.                FILE_CNT(fontfp) = (int)statbuf.st_size;
  1557.                }
  1558.             else            /* failure */
  1559.                {
  1560.                (void)rewind(fontfp);
  1561.                (void)free(p);    /* free dynamic buffer */
  1562.                }
  1563.             }
  1564.          if (DBGOPT(DBG_FONT_CACHE))
  1565.             {
  1566.             (void)fprintf(stderr,"\nopenfont(): Font file %d [%s] ",
  1567.             (int)fileno(fontfp),fontptr->name);
  1568.             if (p == (char *)NULL)
  1569.                (void)fprintf(stderr,
  1570.                "cannot callocate buffer for entire file\n");
  1571.             else
  1572.                (void)fprintf(stderr,
  1573.             "buffer length 0x%x\told buffer at 0x%lx\t\
  1574. new buffer at 0x%lx\n",
  1575.             (int)statbuf.st_size,
  1576.             (long)virt_save[fileno(fontfp)].base,
  1577.             (long)FILE_BASE(fontfp));
  1578.             }
  1579.          }
  1580. #endif
  1581.       } /* end if (file is in open list) */
  1582.  
  1583.    pfontptr = fontptr;            /* make previous = current font */
  1584.    fontptr->font_file_id = fontfp;    /* set file identifier */
  1585.    font_files[current].use_count++;    /* update reference count */
  1586.    }
  1587.  
  1588. #if    VIRTUAL_FONTS
  1589. void virtfree(fp)                /* free buffer space before close */
  1590. FILE *fp;
  1591.    {
  1592.    if (virt_font && (fp != (FILE*)NULL) &&
  1593.       (virt_save[fileno(fp)].base != (char *)NULL))
  1594.       {
  1595.       (void)fflush(fp);
  1596.       (void)free(FILE_BASE(fp));
  1597.       FILE_PTR(fp) = virt_save[fileno(fp)].ptr;
  1598.       FILE_CNT(fp) = virt_save[fileno(fp)].cnt;
  1599.       FILE_BASE(fp) = virt_save[fileno(fp)].base;
  1600.       virt_save[fileno(fp)].base = (char *)NULL;
  1601.       }
  1602.    }
  1603. #endif
  1604.  
  1605. void readfont(long int font_k)
  1606.    {
  1607.    unsigned char a, l;
  1608.    unsigned long int c;                /* checksum */
  1609.    unsigned long int d;                /* design size */
  1610.    char n[MAXSTR];
  1611.    unsigned long int s;                /* scale factor */
  1612.    struct font_entry *tfontptr;     /* temporary font_entry pointer */
  1613.  
  1614.    c = nosignex(dvifp,(unsigned char)4);
  1615.    s = nosignex(dvifp,(unsigned char)4);
  1616.    d = nosignex(dvifp,(unsigned char)4);
  1617.    a = (unsigned char)nosignex(dvifp,(unsigned char)1);
  1618.    l = (unsigned char)nosignex(dvifp,(unsigned char)1);
  1619.    (void)getbytes(dvifp, n, (unsigned char)(a+l));
  1620.    n[a+l] = '\0';
  1621.    tfontptr = (struct font_entry*)malloc((unsigned)sizeof(struct font_entry));
  1622.    if (tfontptr == (struct font_entry *)NULL)
  1623.       (void)fatal(
  1624.       "readfont():  No allocable memory space left for font_entry");
  1625.    tfontptr->next = hfontptr;
  1626.  
  1627.    fontptr = hfontptr = tfontptr;
  1628.    fontptr->k = font_k;
  1629.    fontptr->c = c;
  1630.    fontptr->s = s;
  1631.    fontptr->d = d;
  1632.    fontptr->a = a;
  1633.    fontptr->l = l;
  1634.    (void)strcpy(fontptr->n, n);
  1635.    fontptr->font_space = (long int)(s/6);
  1636.    (void)reldfont(fontptr);
  1637.    }
  1638.  
  1639.  
  1640. int readgf()    /* return 0 on success, EOF on failure */
  1641.    {
  1642.    unsigned long int checksum;
  1643.    register struct char_entry *tcharptr;/* temporary char_entry pointer */
  1644.    register unsigned char the_byte;
  1645.    register unsigned int the_char;    /* loop index */
  1646.  
  1647.    /*
  1648.     Read a GF  file postamble, extracting  character metrics and  raster
  1649.     locations.  The character xoffp, yoffp,  wp, and hp values will  not
  1650.     be filled in until a character raster description is actually called
  1651.     for.
  1652.     */
  1653.  
  1654.    /******************************************************************/
  1655.  
  1656.    /* Process the post-postamble */
  1657.  
  1658.    if (fseek(fontfp,-4L,2))    /* start 4 bytes from end-of-file */
  1659.       {
  1660.       (void)warning("readgf():  fseek() failed--GF font file may be empty");
  1661.       return(EOF);
  1662.       }
  1663.  
  1664.    while ((the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1)) == GFEOF)
  1665.       {
  1666.       if (fseek(fontfp,-2L,1))/* backup 2 bytes to read previous one */
  1667.          {
  1668.          (void)warning(
  1669.          "readgf():  fseek() failed to find GF font file EOF trailer bytes");
  1670.          return(EOF);
  1671.          }
  1672.       }
  1673.  
  1674.    if (the_byte != (unsigned char)GFID)
  1675.       {
  1676.       (void)warning("readgf():  GF font file ID byte not found");
  1677.       return(EOF);
  1678.       }
  1679.  
  1680.    if (fseek(fontfp,-6L,1))    /* backup to read post_post */
  1681.       {
  1682.       (void)warning(
  1683.       "readgf():  fseek() failed to find GF font file POSTPOST byte");
  1684.       return(EOF);
  1685.       }
  1686.  
  1687.    if ((unsigned char)nosignex(fontfp,(unsigned char)1) != (unsigned char)GFPOSTPOST)
  1688.       {
  1689.       (void)warning("readgf():  GF font file POSTPOST byte not found");
  1690.       return(EOF);
  1691.       }
  1692.  
  1693.    if (fseek(fontfp,(long)nosignex(fontfp,(unsigned char)4),0))
  1694.       {        /* position to start of postamble */
  1695.       (void)warning(
  1696.       "readgf():  fseek() failed to find postamble in GF font file");
  1697.       return(EOF);
  1698.       }
  1699.  
  1700.    /******************************************************************/
  1701.  
  1702.    /* Process the postamble */
  1703.  
  1704.    if ((unsigned char)nosignex(fontfp,(unsigned char)1) != (unsigned char)GFPOST)
  1705.       {
  1706.       (void)warning("readgf():  GF font file POST byte not found");
  1707.       return(EOF);
  1708.       }
  1709.  
  1710.    (void)nosignex(fontfp,(unsigned char)4);    /* discard special pointer p[4] */
  1711.  
  1712.    fontptr->designsize = nosignex(fontfp,(unsigned char)4);
  1713.  
  1714.    checksum = nosignex(fontfp,(unsigned char)4);
  1715.    if ((fontptr->c != 0L) && (checksum != 0L) && (fontptr->c != checksum))
  1716.       {
  1717.       (void)sprintf(message,
  1718.       "readgf():  font [%s] has checksum = 10#%010lu [16#%08lx] [8#%011lo] \
  1719. different from DVI checksum = 10#%010lu [16#%08lx] [8#%011lo].  \
  1720. TeX preloaded .fmt file is probably out-of-date with respect to new fonts.",
  1721.       fontptr->name, fontptr->c, fontptr->c, fontptr->c,
  1722.       checksum, checksum, checksum);
  1723.       (void)warning(message);
  1724.       }
  1725.  
  1726.    fontptr->hppp = (unsigned long int)nosignex(fontfp,(unsigned char)4);
  1727.    fontptr->vppp = (unsigned long int)nosignex(fontfp,(unsigned char)4);
  1728.    fontptr->min_m = (long int)signex(fontfp,(unsigned char)4);
  1729.    fontptr->max_m = (long int)signex(fontfp,(unsigned char)4);
  1730.    fontptr->min_n = (long int)signex(fontfp,(unsigned char)4);
  1731.    fontptr->max_n = (long int)signex(fontfp,(unsigned char)4);
  1732.  
  1733.    fontptr->magnification = (unsigned long int)( 0.5 + 5.0 * 72.27 *
  1734.       (double)(fontptr->hppp) / 65536.0 );    /* from GFtoPXL Section 53 */
  1735.  
  1736.    /******************************************************************/
  1737.  
  1738.    /* Process the character locators */
  1739.  
  1740.    the_byte = (unsigned char)GFNOOP;
  1741.    while (the_byte == (unsigned char)GFNOOP)
  1742.       {
  1743.       switch(the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1))
  1744.          {
  1745.       case GFCHLOC:
  1746.       case GFCHLOC0:
  1747.          the_char = (unsigned int)nosignex(fontfp,(unsigned char)1);
  1748.          /* character number MOD 256 */
  1749.          if (the_char >= NPXLCHARS)
  1750.             {
  1751.             (void)warning(
  1752.             "readgf():  GF font file character number is too big for me");
  1753.             return(EOF);
  1754.             }
  1755.          tcharptr = &(fontptr->ch[the_char]);
  1756.          if (the_byte == (unsigned char)GFCHLOC)    /* long form */
  1757.             {
  1758.             tcharptr->dx = (long int)signex(fontfp,(unsigned char)4);
  1759.             tcharptr->dy = (long int)signex(fontfp,(unsigned char)4);
  1760.             }
  1761.          else    /* short form */
  1762.             {
  1763.             tcharptr->dx = (long int)(((unsigned long int)nosignex(fontfp,(unsigned char)1)) <<
  1764.                16);
  1765.             tcharptr->dy = 0L;
  1766.             }
  1767.          tcharptr->tfmw = (unsigned long int)(((double)nosignex(fontfp,(unsigned char)4) *
  1768.             (double)fontptr->s) / (double)(1L << 20));
  1769.          tcharptr->pxlw = (unsigned int)PIXROUND(tcharptr->dx, 1.0/65536.0);
  1770.          tcharptr->fontrp = (long)signex(fontfp,(unsigned char)4);
  1771.  
  1772.          the_byte = (unsigned char)GFNOOP;    /* to force loop continuation */
  1773.          break;
  1774.  
  1775.       case GFNOOP:
  1776.          break;
  1777.  
  1778.       default:    /* this causes loop exit */
  1779.          break;
  1780.          }    /* end switch */
  1781.       }    /* end while */
  1782.  
  1783.    for (the_char = FIRSTPXLCHAR; the_char <= LASTPXLCHAR; the_char++)
  1784.       {    /* Get remaining character metrics, and ignore error returns for now. */
  1785.       tcharptr = &(fontptr->ch[the_char]);
  1786.       if (tcharptr->fontrp >= 0L)
  1787.          (void)chargf((unsigned char)the_char,(void(*)())NULL);
  1788.       }
  1789.  
  1790.    return(0);
  1791.    }
  1792.  
  1793. int readpk()    /* return 0 on success, EOF on failure */
  1794.    {
  1795.    unsigned long int checksum;
  1796.    long end_of_packet;    /* pointer to byte following character packet */
  1797.    register unsigned char flag_byte;
  1798.    unsigned long int packet_length;
  1799.    long start_of_packet;    /* pointer to start of character packet */
  1800.    register struct char_entry *tcharptr;/* temporary char_entry pointer */
  1801.    register unsigned long int the_char;
  1802.  
  1803.    /* Read a PK file, extracting character metrics and raster
  1804.        locations. */
  1805.  
  1806.    /******************************************************************/
  1807.  
  1808.    /* Process the preamble parameters */
  1809.  
  1810.    (void)rewind(fontfp);    /* start at beginning of file */
  1811.    if ((unsigned char)nosignex(fontfp,(unsigned char)1) != PKPRE)
  1812.       {
  1813.       (void)warning("readpk():  PK font file does not start with PRE byte");
  1814.       return(EOF);
  1815.       }
  1816.    if ((unsigned char)nosignex(fontfp,(unsigned char)1) != PKID)
  1817.       {
  1818.       (void)warning(
  1819.       "readpk():  PK font file PRE byte not followed by ID byte");
  1820.       return(EOF);
  1821.       }
  1822.  
  1823.    if (fseek(fontfp,(long)nosignex(fontfp,(unsigned char)1),1))
  1824.       {
  1825.       (void)warning("readpk():  PK font file has garbled comment string");
  1826.       return(EOF);        /* skip comment string */
  1827.       }
  1828.  
  1829.    fontptr->designsize = nosignex(fontfp,(unsigned char)4);
  1830.  
  1831.    checksum = nosignex(fontfp,(unsigned char)4);    /* checksum */
  1832.    if ((fontptr->c != 0L) && (checksum != 0L) && (fontptr->c != checksum))
  1833.       {
  1834.       (void)sprintf(message,
  1835.       "readpk():  font [%s] has checksum = 10#%010lu [16#%08lx] [8#%011lo] \
  1836. different from DVI checksum = 10#%010lu [16#%08lx] [8#%011lo].  \
  1837. TeX preloaded .fmt file is probably out-of-date with respect to new fonts.",
  1838.       fontptr->name, fontptr->c, fontptr->c, fontptr->c,
  1839.       checksum, checksum, checksum);
  1840.       (void)warning(message);
  1841.       }
  1842.  
  1843.    fontptr->hppp = (unsigned long int)nosignex(fontfp,(unsigned char)4);
  1844.    fontptr->vppp = (unsigned long int)nosignex(fontfp,(unsigned char)4);
  1845.  
  1846.    fontptr->min_m = 0L;    /* these are unused in PK format */
  1847.    fontptr->max_m = 0L;
  1848.    fontptr->min_n = 0L;
  1849.    fontptr->max_n = 0L;
  1850.  
  1851.    fontptr->magnification = (unsigned long int)( 0.5 + 5.0 * 72.27 *
  1852.       (double)(fontptr->hppp) / 65536.0 );    /* from GFtoPXL Section 53 */
  1853.  
  1854.    /******************************************************************/
  1855.    /* Process the characters until the POST byte is reached */
  1856.  
  1857.    (void)skpkspec();    /* skip any PK specials */
  1858.  
  1859.    start_of_packet = (long)ftell(fontfp);
  1860.    while ((flag_byte = (unsigned char)nosignex(fontfp,(unsigned char)1)) != PKPOST)
  1861.       {
  1862.       flag_byte &= 0x07;
  1863.       switch(flag_byte)    /* flag_byte is in 0..7 */
  1864.          {
  1865.       case 0:
  1866.       case 1:
  1867.       case 2:
  1868.       case 3:        /* short character preamble */
  1869.          packet_length = (unsigned long int)flag_byte;
  1870.          packet_length <<= 8;
  1871.          packet_length += (unsigned long int)nosignex(fontfp,(unsigned char)1);
  1872.          the_char = (unsigned long int)nosignex(fontfp,(unsigned char)1);
  1873.          if (the_char >= NPXLCHARS)
  1874.             {
  1875.             (void)warning(
  1876.             "readpk():  PK font file character number is too big for me");
  1877.             return(EOF);
  1878.             }
  1879.          tcharptr = &(fontptr->ch[the_char]);
  1880.          end_of_packet = (long)ftell(fontfp) + (long)packet_length;
  1881.          tcharptr->tfmw = (unsigned long int)(((double)nosignex(fontfp,(unsigned char)3) *
  1882.             (double)fontptr->s) / (double)(1L << 20));
  1883.          tcharptr->dx = (long int)nosignex(fontfp,(unsigned char)1) << 16;
  1884.          tcharptr->dy = 0L;
  1885.          tcharptr->pxlw = (unsigned int)PIXROUND(tcharptr->dx, 1.0/65536.0);
  1886.          tcharptr->wp = (int)nosignex(fontfp,(unsigned char)1);
  1887.          tcharptr->hp = (int)nosignex(fontfp,(unsigned char)1);
  1888.          tcharptr->xoffp = (int)signex(fontfp,(unsigned char)1);
  1889.          tcharptr->yoffp = (int)signex(fontfp,(unsigned char)1);
  1890.          break;
  1891.  
  1892.       case 4:
  1893.       case 5:
  1894.       case 6:        /* extended short character preamble */
  1895.          packet_length = (unsigned long int)(flag_byte & 0x03);
  1896.          packet_length <<= 16;
  1897.          packet_length += (unsigned long int)nosignex(fontfp,(unsigned char)2);
  1898.          the_char = (unsigned long int)nosignex(fontfp,(unsigned char)1);
  1899.          if (the_char >= NPXLCHARS)
  1900.             {
  1901.             (void)warning(
  1902.             "readpk():  PK font file character number is too big for me");
  1903.             return(EOF);
  1904.             }
  1905.          tcharptr = &(fontptr->ch[the_char]);
  1906.          end_of_packet = (long)ftell(fontfp) + (long)packet_length;
  1907.          tcharptr->tfmw = (unsigned long int)(((double)nosignex(fontfp,(unsigned char)3) *
  1908.             (double)fontptr->s) / (double)(1L << 20));
  1909.          tcharptr->dx = (long int)nosignex(fontfp,(unsigned char)2) << 16;
  1910.          tcharptr->dy = 0L;
  1911.          tcharptr->pxlw = (unsigned int)PIXROUND(tcharptr->dx, 1.0/65536.0);
  1912.          tcharptr->wp = (int)nosignex(fontfp,(unsigned char)2);
  1913.          tcharptr->hp = (int)nosignex(fontfp,(unsigned char)2);
  1914.          tcharptr->xoffp = (int)signex(fontfp,(unsigned char)2);
  1915.          tcharptr->yoffp = (int)signex(fontfp,(unsigned char)2);
  1916.          break;
  1917.  
  1918.       case 7:        /* long character preamble */
  1919.          packet_length = (unsigned long int)nosignex(fontfp,(unsigned char)4);
  1920.          the_char = (unsigned long int)nosignex(fontfp,(unsigned char)4);
  1921.          if (the_char >= NPXLCHARS)
  1922.             {
  1923.             (void)warning(
  1924.             "readpk():  PK font file character number is too big for me");
  1925.             return(EOF);
  1926.             }
  1927.          tcharptr = &(fontptr->ch[the_char]);
  1928.          end_of_packet = (long)ftell(fontfp) + (long)packet_length;
  1929.          tcharptr->tfmw = (unsigned long int)(((double)nosignex(fontfp,(unsigned char)4) *
  1930.             (double)fontptr->s) / (double)(1L << 20));
  1931.          tcharptr->dx = (long int)signex(fontfp,(unsigned char)4);
  1932.          tcharptr->dy = (long int)signex(fontfp,(unsigned char)4);
  1933.          tcharptr->pxlw = (unsigned int)PIXROUND(tcharptr->dx, 1.0/65536.0);
  1934.          tcharptr->wp = (int)nosignex(fontfp,(unsigned char)4);
  1935.          tcharptr->hp = (int)nosignex(fontfp,(unsigned char)4);
  1936.          tcharptr->xoffp = (int)signex(fontfp,(unsigned char)4);
  1937.          tcharptr->yoffp = (int)signex(fontfp,(unsigned char)4);
  1938.          break;
  1939.          } /* end switch */
  1940.       tcharptr->fontrp = start_of_packet;
  1941.       (void)fseek(fontfp,end_of_packet,0); /* position to end of packet */
  1942.       (void)skpkspec();    /* skip any PK specials */
  1943.       start_of_packet = (long)ftell(fontfp);
  1944.       } /* end while */
  1945.  
  1946.    return(0);
  1947.    }
  1948.  
  1949. /***********************************************************************
  1950. This routine is used  to read in the  postamble values.  It  initializes
  1951. the magnification and checks the stack height prior to starting printing
  1952. the document.
  1953. ***********************************************************************/
  1954.  
  1955. void readpost()
  1956.    {
  1957.    long lastpageptr;        /* byte pointer to last physical page */
  1958.    int the_page_count;        /* page count from DVI file */
  1959.  
  1960.    findpost();
  1961.    if ((unsigned char)nosignex(dvifp,(unsigned char)1) != POST)
  1962.       (void)fatal("readpost():  POST missing at head of postamble");
  1963.  
  1964.    lastpageptr = (long)nosignex(dvifp,(unsigned char)4);
  1965.    num = nosignex(dvifp,(unsigned char)4);
  1966.    den = nosignex(dvifp,(unsigned char)4);
  1967.    mag = nosignex(dvifp,(unsigned char)4);
  1968.    conv = ((double)num/(double)den) *
  1969.       ((double)runmag/(double)STDMAG) *
  1970.       actfact(mag) *
  1971.       ((double)RESOLUTION/254000.0);
  1972.    /* denominator/numerator here since will be dividing by the conversion
  1973.        factor */
  1974.    (void) nosignex(dvifp,(unsigned char)4);    /* height-plus-depth of tallest page */
  1975.    (void) nosignex(dvifp,(unsigned char)4);    /* width of widest page */
  1976.    if ((int)nosignex(dvifp,(unsigned char)2) >= STACKSIZE)
  1977.       (void)fatal("readpost():  Stack size is too small");
  1978.  
  1979.    the_page_count = (int)nosignex(dvifp,(unsigned char)2);
  1980.  
  1981.    if (!quiet)
  1982.       {
  1983.       (void)fprintf(stderr,"[%d pages]",the_page_count);
  1984.       NEWLINE(stderr);
  1985.  
  1986.       (void)fprintf(stderr,"[%d magnification]",(int)runmag);
  1987.       NEWLINE(stderr);
  1988.       }
  1989.  
  1990.    if (preload)
  1991.       getfntdf();
  1992.    getpgtab(lastpageptr);
  1993.    }
  1994.  
  1995.  
  1996. int readpxl()    /* return 0 on success, EOF on failure */
  1997.    {
  1998.    unsigned long int checksum;
  1999.    register struct char_entry *tcharptr;/* temporary char_entry pointer */
  2000.    register unsigned int the_char;        /* loop index */
  2001.  
  2002.    if (fseek(fontfp,-20L,2))    /* 20 bytes before end-of-file for checksum */
  2003.       {
  2004.       (void)warning("readpxl():  fseek() failed--PXL font file may be empty");
  2005.       return(EOF);
  2006.       }
  2007.  
  2008.    checksum = nosignex(fontfp,(unsigned char)4);
  2009.    if ((fontptr->c != 0L) && (checksum != 0L) && (fontptr->c != checksum))
  2010.       {
  2011.       (void)sprintf(message,
  2012.       "readpxl():  font [%s] has checksum = 10#%010lu [16#%08lx] [8#%011lo] \
  2013. different from DVI checksum = 10#%010lu [16#%08lx] [8#%011lo].  \
  2014. TeX preloaded .fmt file is probably out-of-date with respect to new fonts.",
  2015.       fontptr->name, fontptr->c, fontptr->c, fontptr->c,
  2016.       checksum, checksum, checksum);
  2017.       (void)warning(message);
  2018.       }
  2019.    fontptr->magnification = nosignex(fontfp,(unsigned char)4);
  2020.    fontptr->designsize = nosignex(fontfp,(unsigned char)4);
  2021.    if (fseek(fontfp, (long)(nosignex(fontfp,(unsigned char)4) << 2), 0))
  2022.       {
  2023.       (void)warning(
  2024.       "readpxl():  fseek() did not find PXL font file character directory");
  2025.       return(EOF);
  2026.       }
  2027.  
  2028.    for (the_char = FIRSTPXLCHAR; the_char <= LASTPXLCHAR; the_char++)
  2029.       {
  2030.       tcharptr = &(fontptr->ch[the_char]);
  2031.       tcharptr->wp = (int)nosignex(fontfp,(unsigned char)2);
  2032.       tcharptr->hp = (int)nosignex(fontfp,(unsigned char)2);
  2033.       tcharptr->xoffp = (int)signex(fontfp,(unsigned char)2);
  2034.       tcharptr->yoffp = (int)signex(fontfp,(unsigned char)2);
  2035.  
  2036.       /* convert (32-bit) word pointer to byte pointer */
  2037.       tcharptr->fontrp = (long)(nosignex(fontfp,(unsigned char)4) << 2);
  2038.  
  2039.       tcharptr->tfmw = (unsigned long int)(((double)nosignex(fontfp,(unsigned char)4) *
  2040.          (double)fontptr->s) / (double)(1L<<20));
  2041.       tcharptr->pxlw = (unsigned int)PIXROUND((long int)(tcharptr->tfmw), conv);
  2042.       tcharptr->refcount = 0;            /* character unused */
  2043.       tcharptr->rasters = (unsigned long int*)NULL;    /* no raster description */
  2044.       }
  2045.  
  2046.    return(0);
  2047.    }
  2048.  
  2049. void reldfont(tfontptr)        /* load (or reload) font parameters */
  2050. struct font_entry *tfontptr;
  2051.    {
  2052.    register unsigned int the_char;    /* loop index */
  2053.    int err_code;
  2054.    register struct char_entry *tcharptr;/* temporary char_entry pointer */
  2055.  
  2056.    tfontptr->font_mag = (unsigned long int)((actfact(
  2057.    MAGSIZE((double)tfontptr->s/(double)tfontptr->d)) *
  2058.       ((double)runmag/(double)STDMAG) *
  2059.       actfact(mag) *
  2060.       (double)RESOLUTION * 5.0) + 0.5);
  2061.  
  2062.    tfontptr->designsize = (unsigned long int)0L;
  2063.    tfontptr->hppp = (unsigned long int)0L;
  2064.    tfontptr->vppp = (unsigned long int)0L;
  2065.    tfontptr->min_m = (long int)0L;
  2066.    tfontptr->max_m = (long int)0L;
  2067.    tfontptr->min_n = (long int)0L;
  2068.    tfontptr->max_n = (long int)0L;
  2069.  
  2070.    for (the_char = FIRSTPXLCHAR; the_char <= LASTPXLCHAR; the_char++)
  2071.       {
  2072.       tcharptr = &(tfontptr->ch[the_char]);
  2073.       tcharptr->dx = (long int)0L;
  2074.       tcharptr->dy = (long int)0L;
  2075.       tcharptr->hp = (int)0;
  2076.       tcharptr->fontrp = -1L;
  2077.       tcharptr->pxlw = (unsigned int)0;
  2078.       tcharptr->rasters = (unsigned long int*)NULL;
  2079.       tcharptr->refcount = 0;
  2080.       tcharptr->tfmw = 0L;
  2081.       tcharptr->wp = (int)0;
  2082.       tcharptr->xoffp = (int)0;
  2083.       tcharptr->yoffp = (int)0;
  2084.       }
  2085.  
  2086.    if (tfontptr != pfontptr)
  2087.       (void)openfont(tfontptr->n);
  2088.  
  2089.    if (fontfp == (FILE *)NULL)    /* have empty font with zero metrics */
  2090.       return;
  2091.  
  2092.    for (;;)        /* fake one-trip loop */
  2093.       {    /* test for font types PK, GF, and PXL in order of preference */
  2094.       (void)rewind(fontfp);    /* position to beginning-of-file */
  2095.       if ( ((unsigned char)nosignex(fontfp,(unsigned char)1) == (unsigned char)PKPRE) &&
  2096.          ((unsigned char)nosignex(fontfp,(unsigned char)1) == (unsigned char)PKID) )
  2097.          {
  2098.          tfontptr->font_type = (unsigned char)FT_PK;
  2099.          tfontptr->charxx = (void(*)())charpk;
  2100.          err_code = readpk();
  2101.          break;
  2102.          }
  2103.  
  2104.       (void)rewind(fontfp);    /* position to beginning-of-file */
  2105.       if ( ((unsigned char)nosignex(fontfp,(unsigned char)1) == (unsigned char)GFPRE) &&
  2106.          ((unsigned char)nosignex(fontfp,(unsigned char)1) == (unsigned char)GFID) )
  2107.          {
  2108.          tfontptr->font_type = (unsigned char)FT_GF;
  2109.          tfontptr->charxx = (void(*)())chargf;
  2110.          err_code = readgf();
  2111.          break;
  2112.          }
  2113.  
  2114.       (void)rewind(fontfp);    /* position to beginning-of-file */
  2115.       if (nosignex(fontfp,(unsigned char)4) == (unsigned long int)PXLID)
  2116.          {
  2117.          tfontptr->font_type = (unsigned char)FT_PXL;
  2118.          tfontptr->charxx = (void(*)())charpxl;
  2119.          err_code = readpxl();
  2120.          break;
  2121.          }
  2122.  
  2123.       err_code = (int)EOF;
  2124.       break;
  2125.       } /* end one-trip loop */
  2126.  
  2127.    if (err_code)
  2128.       {
  2129.       (void)sprintf(message,
  2130.       "reldfont():  Font file [%s] is not a valid GF, PK, or PXL file",
  2131.       tfontptr->name);
  2132.       (void)fatal(message);
  2133.       }
  2134.    }
  2135.  
  2136.  
  2137. int rulepxl(number, cnvfac)/* return number of pixels in a rule */
  2138. register unsigned long int number;/* in DVI units       */
  2139. register double cnvfac;    /* conversion factor */
  2140.  
  2141.    {
  2142.    register int n;
  2143.  
  2144.    n = (int)(number*cnvfac);
  2145.    if ((double)n < ((double)(number))*cnvfac)
  2146.       return((int)(n+1));
  2147.    else
  2148.       return((int)n);
  2149.    }
  2150.  
  2151.  
  2152. void setchar(c, update_h)
  2153. register unsigned char c;
  2154. register int update_h;
  2155.    {
  2156.    register struct char_entry *tcharptr;  /* temporary char_entry pointer */
  2157.  
  2158.    if (DBGOPT(DBG_SET_TEXT))
  2159.       {
  2160.       (void)fprintf(stderr,"setchar('");
  2161.       if (isprint(c))
  2162.          (void)putc(c,stderr);
  2163.       else
  2164.          (void)fprintf(stderr,"\\%03o",(int)c);
  2165.       (void)fprintf(stderr,"'<%d>) (hh,vv) = (%ld,%ld) font name <%s>",
  2166.       (int)c, (long)hh, (long)vv, fontptr->n);
  2167.       NEWLINE(stderr);
  2168.       }
  2169.  
  2170.    tcharptr = &(fontptr->ch[c]);
  2171.    if (((hh - tcharptr->xoffp + tcharptr->pxlw) <= XSIZE)
  2172.       && (hh >= 0)
  2173.       && (vv <= YSIZE)
  2174.       && (vv >= 0))
  2175.       {                /* character fits entirely on page */
  2176.       moveto( hh, (int)(YSIZE-vv));
  2177.       dispchar(c);
  2178.       }
  2179.    else if (DBGOPT(DBG_OFF_PAGE) && !quiet)
  2180.       {                /* character is off page -- discard it */
  2181.       (void)fprintf(stderr,
  2182.       "setchar(): Char %c [10#%3d 8#%03o 16#%02x] off page.",
  2183.       isprint(c) ? c : '?',c,c,c);
  2184.       NEWLINE(stderr);
  2185.       }
  2186.  
  2187.    if (update_h)
  2188.       {
  2189.       h += (long int)tcharptr->tfmw;
  2190.       hh += (int)tcharptr->pxlw;
  2191.       hh = (int)(fixpos(hh-lmargin,h,conv) + lmargin);
  2192.       }
  2193.    }
  2194.  
  2195. /***********************************************************************
  2196. This routine is used to specify the  font to be used in printing  future
  2197. characters.
  2198. ***********************************************************************/
  2199.  
  2200. void setfntnm(k)
  2201. register long int k;
  2202.    {
  2203.    register struct font_entry *p;
  2204.  
  2205.    p = hfontptr;
  2206.    while ((p != (struct font_entry *)NULL) && (p->k != k))
  2207.       p = p->next;
  2208.    if (p == (struct font_entry *)NULL)
  2209.       {
  2210.       (void)sprintf(message,"setfntnm():  font %ld undefined", k);
  2211.       (void)fatal(message);
  2212.       }
  2213.    else
  2214.       fontptr = p;
  2215.    }
  2216.  
  2217.  
  2218. /* draw a rule with bottom left corner at (h,v) */
  2219.  
  2220. void setrule(height, width, update_h)
  2221. register unsigned long int height, width;
  2222. register int update_h;
  2223.  
  2224.    {
  2225.  
  2226.    if ((height > 0) && (width > 0))        /* non-empty rule */
  2227.       fillrect(hh, YSIZE-vv,
  2228.             rulepxl(width,conv),
  2229.             rulepxl(height, conv * ((double)YDPI/(double)XDPI)));
  2230.                                     /* fixed for non 1 aspect */
  2231.  
  2232.    if (update_h)
  2233.       {
  2234.       h += (long int)width;
  2235.       hh += rulepxl(width, conv);
  2236.       hh = fixpos(hh-lmargin,h,conv) + lmargin;
  2237.       }
  2238.    }
  2239.  
  2240. long int signex(fp, n)     /* return n byte quantity from file fd */
  2241. register FILE *fp;    /* file pointer     */
  2242. register unsigned char n;      /* number of bytes */
  2243.  
  2244.    {
  2245.    register unsigned char n1; /* number of bytes      */
  2246.    register long int number; /* number being constructed */
  2247.  
  2248.    number = (long int)getc(fp);/* get first (high-order) byte */
  2249.  
  2250.    n1 = n--;
  2251.    while (n--)
  2252.       {
  2253.       number <<= 8;
  2254.       number |= (long int)getc(fp);
  2255.       }
  2256.  
  2257.    /* NOTE: This code assumes that the right-shift is an arithmetic, rather
  2258.     than logical, shift which will propagate the sign bit right.   According
  2259.     to Kernighan and Ritchie, this is compiler dependent! */
  2260.  
  2261.    number<<=32-8*n1;
  2262.  
  2263.    number>>=32-8*n1;  /* sign extend */
  2264.  
  2265.    return((long int)number);
  2266.    }
  2267.  
  2268.  
  2269. void skgfspec()    /* Skip GF font file specials */
  2270.    {
  2271.    unsigned char the_byte;
  2272.  
  2273.    the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
  2274.    while ((the_byte >= (unsigned char)GFXXX1) && (the_byte != GFPOST))
  2275.       {
  2276.       switch(the_byte)
  2277.          {
  2278.       case GFXXX1:
  2279.          (void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)1),1);
  2280.          break;
  2281.  
  2282.       case GFXXX2:
  2283.          (void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)2),1);
  2284.          break;
  2285.  
  2286.       case GFXXX3:
  2287.          (void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)3),1);
  2288.          break;
  2289.  
  2290.       case GFXXX4:
  2291.          (void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)4),1);
  2292.          break;
  2293.  
  2294.       case GFYYY:
  2295.          (void)nosignex(fontfp,(unsigned char)4);
  2296.          break;
  2297.  
  2298.       case GFNOOP:
  2299.          break;
  2300.  
  2301.       default:
  2302.          (void)sprintf(message,"skgfspec():  Bad GF font file [%s]",
  2303.          fontptr->name);
  2304.          (void)fatal(message);
  2305.          }
  2306.       the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
  2307.       }
  2308.    (void)ungetc((char)the_byte,fontfp);    /* put back lookahead byte */
  2309.    }
  2310.  
  2311.  
  2312. void skipfont( long int k)
  2313.    {
  2314.    unsigned char a, l;
  2315.    char n[MAXSTR];
  2316.  
  2317.    (void) nosignex(dvifp,(unsigned char)4);
  2318.    (void) nosignex(dvifp,(unsigned char)4);
  2319.    (void) nosignex(dvifp,(unsigned char)4);
  2320.    a = (unsigned char) nosignex(dvifp,(unsigned char)1);
  2321.    l = (unsigned char) nosignex(dvifp,(unsigned char)1);
  2322.    getbytes(dvifp, n, (unsigned char)(a+l));
  2323.    }
  2324.  
  2325. void skpkspec()    /* Skip PK font file specials */
  2326.    {
  2327.    unsigned char the_byte;
  2328.  
  2329.    the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
  2330.    while ((the_byte >= (unsigned char)PKXXX1) && (the_byte != PKPOST))
  2331.       {
  2332.       switch(the_byte)
  2333.          {
  2334.       case PKXXX1:
  2335.          (void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)1),1);
  2336.          break;
  2337.  
  2338.       case PKXXX2:
  2339.          (void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)2),1);
  2340.          break;
  2341.  
  2342.       case PKXXX3:
  2343.          (void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)3),1);
  2344.          break;
  2345.  
  2346.       case PKXXX4:
  2347.          (void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)4),1);
  2348.          break;
  2349.  
  2350.       case PKYYY:
  2351.          (void)nosignex(fontfp,(unsigned char)4);
  2352.          break;
  2353.  
  2354.       case PKNOOP:
  2355.          break;
  2356.  
  2357.       default:
  2358.          (void)sprintf(message,"skpkspec():  Bad PK font file [%s]",
  2359.          fontptr->name);
  2360.          (void)fatal(message);
  2361.          }
  2362.       the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
  2363.       }
  2364.    (void)ungetc((char)the_byte,fontfp);    /* put back lookahead byte */
  2365.    }
  2366.  
  2367.  
  2368. void special(s)            /* process TeX \special{} string in s[] */
  2369. register char *s;
  2370.    {
  2371.    (void)sprintf(message,
  2372.    "special():  TeX \\special{%s} not implemented in this driver",s);
  2373.    (void)warning(message);
  2374.    }
  2375.  
  2376. void outrow(c,yoff)    /* copy img_row[] into rasters[] if allocated, else no-op */
  2377. unsigned char c;        /* current character value */
  2378. unsigned int yoff;    /* offset from top row (0,1,...,hp-1) */
  2379.    {
  2380.    register unsigned int k;    /* loop index */
  2381.    register unsigned long int *p;    /* pointer into img_row[] */
  2382.    register unsigned long int *q;    /* pointer into rasters[] */
  2383.    register struct char_entry *tcharptr; /* temporary char_entry pointer */
  2384.    unsigned int words_per_row;    /* number of raster words to copy */
  2385.  
  2386.    tcharptr = &(fontptr->ch[c]);
  2387.    if (tcharptr->rasters != (unsigned long int*)NULL)
  2388.       {
  2389.       words_per_row = (unsigned int)(tcharptr->wp + 31) >> 5;
  2390.       p = tcharptr->rasters + yoff*words_per_row;
  2391.       q = img_row;
  2392.       for (k = words_per_row; k; --k)    /* copy img_row[] into rasters[] */
  2393.          *p++ = *q++;
  2394.       }
  2395.    }
  2396.  
  2397.  
  2398.